blob: 3204cf08ecd766e8e3ca34154dd151625ede6dab [file] [log] [blame]
Daniel Dunbar921b9682008-10-04 19:21:03 +00001//===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the language specific #pragma handlers.
11//
12//===----------------------------------------------------------------------===//
13
Hans Wennborg899ded92014-10-16 20:52:46 +000014#include "clang/AST/ASTContext.h"
Nico Weber66220292016-03-02 17:28:48 +000015#include "clang/Basic/PragmaKinds.h"
David Majnemerad2986e2014-08-14 06:35:08 +000016#include "clang/Basic/TargetInfo.h"
Eli Bendersky06a40422014-06-06 20:31:48 +000017#include "clang/Lex/Preprocessor.h"
Richard Trieu0614cff2018-11-28 04:36:31 +000018#include "clang/Parse/LoopHint.h"
Eli Bendersky06a40422014-06-06 20:31:48 +000019#include "clang/Parse/ParseDiagnostic.h"
20#include "clang/Parse/Parser.h"
Vassil Vassilev11ad3392017-03-23 15:11:07 +000021#include "clang/Parse/RAIIObjectsForParser.h"
Eli Bendersky06a40422014-06-06 20:31:48 +000022#include "clang/Sema/Scope.h"
23#include "llvm/ADT/StringSwitch.h"
24using namespace clang;
Daniel Dunbar921b9682008-10-04 19:21:03 +000025
Reid Kleckner5b086462014-02-20 22:52:09 +000026namespace {
27
28struct PragmaAlignHandler : public PragmaHandler {
29 explicit PragmaAlignHandler() : PragmaHandler("align") {}
Craig Topper2b07f022014-03-12 05:09:18 +000030 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
31 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000032};
33
34struct PragmaGCCVisibilityHandler : public PragmaHandler {
35 explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
Craig Topper2b07f022014-03-12 05:09:18 +000036 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
37 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000038};
39
40struct PragmaOptionsHandler : public PragmaHandler {
41 explicit PragmaOptionsHandler() : PragmaHandler("options") {}
Craig Topper2b07f022014-03-12 05:09:18 +000042 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
43 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000044};
45
46struct PragmaPackHandler : public PragmaHandler {
47 explicit PragmaPackHandler() : PragmaHandler("pack") {}
Craig Topper2b07f022014-03-12 05:09:18 +000048 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
49 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000050};
51
Javed Absar2a67c9e2017-06-05 10:11:57 +000052struct PragmaClangSectionHandler : public PragmaHandler {
53 explicit PragmaClangSectionHandler(Sema &S)
54 : PragmaHandler("section"), Actions(S) {}
55 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
56 Token &FirstToken) override;
57private:
58 Sema &Actions;
59};
60
Reid Kleckner5b086462014-02-20 22:52:09 +000061struct PragmaMSStructHandler : public PragmaHandler {
62 explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
Craig Topper2b07f022014-03-12 05:09:18 +000063 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
64 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000065};
66
67struct PragmaUnusedHandler : public PragmaHandler {
68 PragmaUnusedHandler() : PragmaHandler("unused") {}
Craig Topper2b07f022014-03-12 05:09:18 +000069 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
70 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000071};
72
73struct PragmaWeakHandler : public PragmaHandler {
74 explicit PragmaWeakHandler() : PragmaHandler("weak") {}
Craig Topper2b07f022014-03-12 05:09:18 +000075 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
76 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000077};
78
79struct PragmaRedefineExtnameHandler : public PragmaHandler {
80 explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
Craig Topper2b07f022014-03-12 05:09:18 +000081 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
82 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000083};
84
85struct PragmaOpenCLExtensionHandler : public PragmaHandler {
86 PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
Craig Topper2b07f022014-03-12 05:09:18 +000087 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
88 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000089};
90
91
92struct PragmaFPContractHandler : public PragmaHandler {
93 PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
Craig Topper2b07f022014-03-12 05:09:18 +000094 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
95 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
104 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
105 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)));
121 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Steven Wub96a3a42018-01-05 22:45:03 +0000122 }
123};
124
125/// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...".
126struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
127 PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {}
128
129 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
130 Token &Tok) override {
131 tok::OnOffSwitch OOS;
132 PP.LexOnOffSwitch(OOS);
133 }
134};
135
136/// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
137struct PragmaSTDC_UnknownHandler : public PragmaHandler {
138 PragmaSTDC_UnknownHandler() = default;
139
140 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
141 Token &UnknownTok) override {
142 // C99 6.10.6p2, unknown forms are not allowed.
143 PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored);
144 }
145};
146
Adam Nemet60d32642017-04-04 21:18:36 +0000147struct PragmaFPHandler : public PragmaHandler {
148 PragmaFPHandler() : PragmaHandler("fp") {}
149 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
150 Token &FirstToken) override;
151};
152
Reid Kleckner5b086462014-02-20 22:52:09 +0000153struct PragmaNoOpenMPHandler : public PragmaHandler {
154 PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
Craig Topper2b07f022014-03-12 05:09:18 +0000155 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
156 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000157};
158
159struct PragmaOpenMPHandler : public PragmaHandler {
160 PragmaOpenMPHandler() : PragmaHandler("omp") { }
Craig Topper2b07f022014-03-12 05:09:18 +0000161 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
162 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000163};
164
165/// PragmaCommentHandler - "\#pragma comment ...".
166struct PragmaCommentHandler : public PragmaHandler {
167 PragmaCommentHandler(Sema &Actions)
168 : PragmaHandler("comment"), Actions(Actions) {}
Craig Topper2b07f022014-03-12 05:09:18 +0000169 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
170 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000171private:
172 Sema &Actions;
173};
174
175struct PragmaDetectMismatchHandler : public PragmaHandler {
176 PragmaDetectMismatchHandler(Sema &Actions)
177 : PragmaHandler("detect_mismatch"), Actions(Actions) {}
Craig Topper2b07f022014-03-12 05:09:18 +0000178 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
179 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000180private:
181 Sema &Actions;
182};
183
184struct PragmaMSPointersToMembers : public PragmaHandler {
185 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
Craig Topper2b07f022014-03-12 05:09:18 +0000186 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
187 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000188};
189
190struct PragmaMSVtorDisp : public PragmaHandler {
191 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
Craig Topper2b07f022014-03-12 05:09:18 +0000192 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
193 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000194};
195
Warren Huntc3b18962014-04-08 22:30:47 +0000196struct PragmaMSPragma : public PragmaHandler {
197 explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000198 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
199 Token &FirstToken) override;
200};
201
Dario Domizioli13a0a382014-05-23 12:13:25 +0000202/// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
203struct PragmaOptimizeHandler : public PragmaHandler {
204 PragmaOptimizeHandler(Sema &S)
205 : PragmaHandler("optimize"), Actions(S) {}
206 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
207 Token &FirstToken) override;
208private:
Eli Bendersky06a40422014-06-06 20:31:48 +0000209 Sema &Actions;
210};
211
212struct PragmaLoopHintHandler : public PragmaHandler {
213 PragmaLoopHintHandler() : PragmaHandler("loop") {}
214 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
215 Token &FirstToken) override;
216};
217
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000218struct PragmaUnrollHintHandler : public PragmaHandler {
219 PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
220 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
221 Token &FirstToken) override;
222};
223
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000224struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
225 PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
226};
227
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000228struct PragmaMSIntrinsicHandler : public PragmaHandler {
229 PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {}
230 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
231 Token &FirstToken) override;
232};
233
Hans Wennborg1bbe00e2018-03-20 08:53:11 +0000234struct PragmaMSOptimizeHandler : public PragmaHandler {
235 PragmaMSOptimizeHandler() : PragmaHandler("optimize") {}
236 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
237 Token &FirstToken) override;
238};
239
Justin Lebar67a78a62016-10-08 22:15:58 +0000240struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
241 PragmaForceCUDAHostDeviceHandler(Sema &Actions)
242 : PragmaHandler("force_cuda_host_device"), Actions(Actions) {}
243 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
244 Token &FirstToken) override;
245
246private:
247 Sema &Actions;
248};
249
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000250/// PragmaAttributeHandler - "\#pragma clang attribute ...".
251struct PragmaAttributeHandler : public PragmaHandler {
252 PragmaAttributeHandler(AttributeFactory &AttrFactory)
253 : PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {}
254 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
255 Token &FirstToken) override;
256
257 /// A pool of attributes that were parsed in \#pragma clang attribute.
258 ParsedAttributes AttributesForPragmaAttribute;
259};
260
Eli Bendersky06a40422014-06-06 20:31:48 +0000261} // end namespace
262
263void Parser::initializePragmaHandlers() {
David Blaikiee0cfc042018-11-15 03:04:23 +0000264 AlignHandler = llvm::make_unique<PragmaAlignHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000265 PP.AddPragmaHandler(AlignHandler.get());
266
David Blaikiee0cfc042018-11-15 03:04:23 +0000267 GCCVisibilityHandler = llvm::make_unique<PragmaGCCVisibilityHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000268 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
269
David Blaikiee0cfc042018-11-15 03:04:23 +0000270 OptionsHandler = llvm::make_unique<PragmaOptionsHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000271 PP.AddPragmaHandler(OptionsHandler.get());
272
David Blaikiee0cfc042018-11-15 03:04:23 +0000273 PackHandler = llvm::make_unique<PragmaPackHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000274 PP.AddPragmaHandler(PackHandler.get());
275
David Blaikiee0cfc042018-11-15 03:04:23 +0000276 MSStructHandler = llvm::make_unique<PragmaMSStructHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000277 PP.AddPragmaHandler(MSStructHandler.get());
278
David Blaikiee0cfc042018-11-15 03:04:23 +0000279 UnusedHandler = llvm::make_unique<PragmaUnusedHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000280 PP.AddPragmaHandler(UnusedHandler.get());
281
David Blaikiee0cfc042018-11-15 03:04:23 +0000282 WeakHandler = llvm::make_unique<PragmaWeakHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000283 PP.AddPragmaHandler(WeakHandler.get());
284
David Blaikiee0cfc042018-11-15 03:04:23 +0000285 RedefineExtnameHandler = llvm::make_unique<PragmaRedefineExtnameHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000286 PP.AddPragmaHandler(RedefineExtnameHandler.get());
287
David Blaikiee0cfc042018-11-15 03:04:23 +0000288 FPContractHandler = llvm::make_unique<PragmaFPContractHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000289 PP.AddPragmaHandler("STDC", FPContractHandler.get());
290
David Blaikiee0cfc042018-11-15 03:04:23 +0000291 STDCFENVHandler = llvm::make_unique<PragmaSTDC_FENV_ACCESSHandler>();
Steven Wub96a3a42018-01-05 22:45:03 +0000292 PP.AddPragmaHandler("STDC", STDCFENVHandler.get());
293
David Blaikiee0cfc042018-11-15 03:04:23 +0000294 STDCCXLIMITHandler = llvm::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>();
Steven Wub96a3a42018-01-05 22:45:03 +0000295 PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get());
296
David Blaikiee0cfc042018-11-15 03:04:23 +0000297 STDCUnknownHandler = llvm::make_unique<PragmaSTDC_UnknownHandler>();
Steven Wub96a3a42018-01-05 22:45:03 +0000298 PP.AddPragmaHandler("STDC", STDCUnknownHandler.get());
299
David Blaikiee0cfc042018-11-15 03:04:23 +0000300 PCSectionHandler = llvm::make_unique<PragmaClangSectionHandler>(Actions);
Javed Absar2a67c9e2017-06-05 10:11:57 +0000301 PP.AddPragmaHandler("clang", PCSectionHandler.get());
302
Reid Kleckner5b086462014-02-20 22:52:09 +0000303 if (getLangOpts().OpenCL) {
David Blaikiee0cfc042018-11-15 03:04:23 +0000304 OpenCLExtensionHandler = llvm::make_unique<PragmaOpenCLExtensionHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000305 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
306
307 PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
308 }
309 if (getLangOpts().OpenMP)
David Blaikiee0cfc042018-11-15 03:04:23 +0000310 OpenMPHandler = llvm::make_unique<PragmaOpenMPHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000311 else
David Blaikiee0cfc042018-11-15 03:04:23 +0000312 OpenMPHandler = llvm::make_unique<PragmaNoOpenMPHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000313 PP.AddPragmaHandler(OpenMPHandler.get());
314
Saleem Abdulrasoolfd4db532018-02-07 01:46:46 +0000315 if (getLangOpts().MicrosoftExt ||
316 getTargetInfo().getTriple().isOSBinFormatELF()) {
David Blaikiee0cfc042018-11-15 03:04:23 +0000317 MSCommentHandler = llvm::make_unique<PragmaCommentHandler>(Actions);
Reid Kleckner5b086462014-02-20 22:52:09 +0000318 PP.AddPragmaHandler(MSCommentHandler.get());
Yunzhong Gao99efc032015-03-23 20:41:42 +0000319 }
320
321 if (getLangOpts().MicrosoftExt) {
David Blaikiee0cfc042018-11-15 03:04:23 +0000322 MSDetectMismatchHandler =
323 llvm::make_unique<PragmaDetectMismatchHandler>(Actions);
Reid Kleckner5b086462014-02-20 22:52:09 +0000324 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
David Blaikiee0cfc042018-11-15 03:04:23 +0000325 MSPointersToMembers = llvm::make_unique<PragmaMSPointersToMembers>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000326 PP.AddPragmaHandler(MSPointersToMembers.get());
David Blaikiee0cfc042018-11-15 03:04:23 +0000327 MSVtorDisp = llvm::make_unique<PragmaMSVtorDisp>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000328 PP.AddPragmaHandler(MSVtorDisp.get());
David Blaikiee0cfc042018-11-15 03:04:23 +0000329 MSInitSeg = llvm::make_unique<PragmaMSPragma>("init_seg");
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000330 PP.AddPragmaHandler(MSInitSeg.get());
David Blaikiee0cfc042018-11-15 03:04:23 +0000331 MSDataSeg = llvm::make_unique<PragmaMSPragma>("data_seg");
Warren Huntc3b18962014-04-08 22:30:47 +0000332 PP.AddPragmaHandler(MSDataSeg.get());
David Blaikiee0cfc042018-11-15 03:04:23 +0000333 MSBSSSeg = llvm::make_unique<PragmaMSPragma>("bss_seg");
Warren Huntc3b18962014-04-08 22:30:47 +0000334 PP.AddPragmaHandler(MSBSSSeg.get());
David Blaikiee0cfc042018-11-15 03:04:23 +0000335 MSConstSeg = llvm::make_unique<PragmaMSPragma>("const_seg");
Warren Huntc3b18962014-04-08 22:30:47 +0000336 PP.AddPragmaHandler(MSConstSeg.get());
David Blaikiee0cfc042018-11-15 03:04:23 +0000337 MSCodeSeg = llvm::make_unique<PragmaMSPragma>("code_seg");
Warren Huntc3b18962014-04-08 22:30:47 +0000338 PP.AddPragmaHandler(MSCodeSeg.get());
David Blaikiee0cfc042018-11-15 03:04:23 +0000339 MSSection = llvm::make_unique<PragmaMSPragma>("section");
Warren Huntc3b18962014-04-08 22:30:47 +0000340 PP.AddPragmaHandler(MSSection.get());
David Blaikiee0cfc042018-11-15 03:04:23 +0000341 MSRuntimeChecks = llvm::make_unique<PragmaMSRuntimeChecksHandler>();
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000342 PP.AddPragmaHandler(MSRuntimeChecks.get());
David Blaikiee0cfc042018-11-15 03:04:23 +0000343 MSIntrinsic = llvm::make_unique<PragmaMSIntrinsicHandler>();
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000344 PP.AddPragmaHandler(MSIntrinsic.get());
David Blaikiee0cfc042018-11-15 03:04:23 +0000345 MSOptimize = llvm::make_unique<PragmaMSOptimizeHandler>();
Hans Wennborg1bbe00e2018-03-20 08:53:11 +0000346 PP.AddPragmaHandler(MSOptimize.get());
Reid Kleckner5b086462014-02-20 22:52:09 +0000347 }
Eli Bendersky06a40422014-06-06 20:31:48 +0000348
Justin Lebar67a78a62016-10-08 22:15:58 +0000349 if (getLangOpts().CUDA) {
David Blaikiee0cfc042018-11-15 03:04:23 +0000350 CUDAForceHostDeviceHandler =
351 llvm::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions);
Justin Lebar67a78a62016-10-08 22:15:58 +0000352 PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
353 }
354
David Blaikiee0cfc042018-11-15 03:04:23 +0000355 OptimizeHandler = llvm::make_unique<PragmaOptimizeHandler>(Actions);
Eli Bendersky06a40422014-06-06 20:31:48 +0000356 PP.AddPragmaHandler("clang", OptimizeHandler.get());
357
David Blaikiee0cfc042018-11-15 03:04:23 +0000358 LoopHintHandler = llvm::make_unique<PragmaLoopHintHandler>();
Eli Bendersky06a40422014-06-06 20:31:48 +0000359 PP.AddPragmaHandler("clang", LoopHintHandler.get());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000360
David Blaikiee0cfc042018-11-15 03:04:23 +0000361 UnrollHintHandler = llvm::make_unique<PragmaUnrollHintHandler>("unroll");
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000362 PP.AddPragmaHandler(UnrollHintHandler.get());
Mark Heffernanc888e412014-07-24 18:09:38 +0000363
David Blaikiee0cfc042018-11-15 03:04:23 +0000364 NoUnrollHintHandler = llvm::make_unique<PragmaUnrollHintHandler>("nounroll");
Mark Heffernanc888e412014-07-24 18:09:38 +0000365 PP.AddPragmaHandler(NoUnrollHintHandler.get());
Adam Nemet60d32642017-04-04 21:18:36 +0000366
David Blaikiee0cfc042018-11-15 03:04:23 +0000367 UnrollAndJamHintHandler =
368 llvm::make_unique<PragmaUnrollHintHandler>("unroll_and_jam");
David Greenc8e39242018-08-01 14:36:12 +0000369 PP.AddPragmaHandler(UnrollAndJamHintHandler.get());
370
David Blaikiee0cfc042018-11-15 03:04:23 +0000371 NoUnrollAndJamHintHandler =
372 llvm::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam");
David Greenc8e39242018-08-01 14:36:12 +0000373 PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get());
374
David Blaikiee0cfc042018-11-15 03:04:23 +0000375 FPHandler = llvm::make_unique<PragmaFPHandler>();
Adam Nemet60d32642017-04-04 21:18:36 +0000376 PP.AddPragmaHandler("clang", FPHandler.get());
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000377
David Blaikiee0cfc042018-11-15 03:04:23 +0000378 AttributePragmaHandler =
379 llvm::make_unique<PragmaAttributeHandler>(AttrFactory);
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000380 PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
Eli Bendersky06a40422014-06-06 20:31:48 +0000381}
382
383void Parser::resetPragmaHandlers() {
Reid Kleckner5b086462014-02-20 22:52:09 +0000384 // Remove the pragma handlers we installed.
385 PP.RemovePragmaHandler(AlignHandler.get());
386 AlignHandler.reset();
387 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
388 GCCVisibilityHandler.reset();
389 PP.RemovePragmaHandler(OptionsHandler.get());
390 OptionsHandler.reset();
391 PP.RemovePragmaHandler(PackHandler.get());
392 PackHandler.reset();
393 PP.RemovePragmaHandler(MSStructHandler.get());
394 MSStructHandler.reset();
395 PP.RemovePragmaHandler(UnusedHandler.get());
396 UnusedHandler.reset();
397 PP.RemovePragmaHandler(WeakHandler.get());
398 WeakHandler.reset();
399 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
400 RedefineExtnameHandler.reset();
401
402 if (getLangOpts().OpenCL) {
403 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
404 OpenCLExtensionHandler.reset();
405 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
406 }
407 PP.RemovePragmaHandler(OpenMPHandler.get());
408 OpenMPHandler.reset();
409
Saleem Abdulrasoolfd4db532018-02-07 01:46:46 +0000410 if (getLangOpts().MicrosoftExt ||
411 getTargetInfo().getTriple().isOSBinFormatELF()) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000412 PP.RemovePragmaHandler(MSCommentHandler.get());
413 MSCommentHandler.reset();
Yunzhong Gao99efc032015-03-23 20:41:42 +0000414 }
415
Javed Absar2a67c9e2017-06-05 10:11:57 +0000416 PP.RemovePragmaHandler("clang", PCSectionHandler.get());
417 PCSectionHandler.reset();
418
Yunzhong Gao99efc032015-03-23 20:41:42 +0000419 if (getLangOpts().MicrosoftExt) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000420 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
421 MSDetectMismatchHandler.reset();
422 PP.RemovePragmaHandler(MSPointersToMembers.get());
423 MSPointersToMembers.reset();
424 PP.RemovePragmaHandler(MSVtorDisp.get());
425 MSVtorDisp.reset();
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000426 PP.RemovePragmaHandler(MSInitSeg.get());
427 MSInitSeg.reset();
Warren Huntc3b18962014-04-08 22:30:47 +0000428 PP.RemovePragmaHandler(MSDataSeg.get());
429 MSDataSeg.reset();
430 PP.RemovePragmaHandler(MSBSSSeg.get());
431 MSBSSSeg.reset();
432 PP.RemovePragmaHandler(MSConstSeg.get());
433 MSConstSeg.reset();
434 PP.RemovePragmaHandler(MSCodeSeg.get());
435 MSCodeSeg.reset();
436 PP.RemovePragmaHandler(MSSection.get());
437 MSSection.reset();
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000438 PP.RemovePragmaHandler(MSRuntimeChecks.get());
439 MSRuntimeChecks.reset();
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000440 PP.RemovePragmaHandler(MSIntrinsic.get());
441 MSIntrinsic.reset();
Hans Wennborg1bbe00e2018-03-20 08:53:11 +0000442 PP.RemovePragmaHandler(MSOptimize.get());
443 MSOptimize.reset();
Reid Kleckner5b086462014-02-20 22:52:09 +0000444 }
445
Justin Lebar67a78a62016-10-08 22:15:58 +0000446 if (getLangOpts().CUDA) {
447 PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get());
448 CUDAForceHostDeviceHandler.reset();
449 }
450
Reid Kleckner5b086462014-02-20 22:52:09 +0000451 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
452 FPContractHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000453
Steven Wub96a3a42018-01-05 22:45:03 +0000454 PP.RemovePragmaHandler("STDC", STDCFENVHandler.get());
455 STDCFENVHandler.reset();
456
457 PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get());
458 STDCCXLIMITHandler.reset();
459
460 PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get());
461 STDCUnknownHandler.reset();
462
Eli Bendersky06a40422014-06-06 20:31:48 +0000463 PP.RemovePragmaHandler("clang", OptimizeHandler.get());
464 OptimizeHandler.reset();
465
466 PP.RemovePragmaHandler("clang", LoopHintHandler.get());
467 LoopHintHandler.reset();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000468
469 PP.RemovePragmaHandler(UnrollHintHandler.get());
470 UnrollHintHandler.reset();
Mark Heffernanc888e412014-07-24 18:09:38 +0000471
472 PP.RemovePragmaHandler(NoUnrollHintHandler.get());
473 NoUnrollHintHandler.reset();
Adam Nemet60d32642017-04-04 21:18:36 +0000474
David Greenc8e39242018-08-01 14:36:12 +0000475 PP.RemovePragmaHandler(UnrollAndJamHintHandler.get());
476 UnrollAndJamHintHandler.reset();
477
478 PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get());
479 NoUnrollAndJamHintHandler.reset();
480
Adam Nemet60d32642017-04-04 21:18:36 +0000481 PP.RemovePragmaHandler("clang", FPHandler.get());
482 FPHandler.reset();
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000483
484 PP.RemovePragmaHandler("clang", AttributePragmaHandler.get());
485 AttributePragmaHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000486}
487
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000488/// Handle the annotation token produced for #pragma unused(...)
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000489///
490/// Each annot_pragma_unused is followed by the argument token so e.g.
491/// "#pragma unused(x,y)" becomes:
492/// annot_pragma_unused 'x' annot_pragma_unused 'y'
493void Parser::HandlePragmaUnused() {
494 assert(Tok.is(tok::annot_pragma_unused));
Richard Smithaf3b3252017-05-18 19:21:48 +0000495 SourceLocation UnusedLoc = ConsumeAnnotationToken();
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000496 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
497 ConsumeToken(); // The argument token.
498}
Eli Friedman570024a2010-08-05 06:57:20 +0000499
Rafael Espindola273fd772012-01-26 02:02:57 +0000500void Parser::HandlePragmaVisibility() {
501 assert(Tok.is(tok::annot_pragma_vis));
502 const IdentifierInfo *VisType =
503 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
Richard Smithaf3b3252017-05-18 19:21:48 +0000504 SourceLocation VisLoc = ConsumeAnnotationToken();
Rafael Espindola273fd772012-01-26 02:02:57 +0000505 Actions.ActOnPragmaVisibility(VisType, VisLoc);
506}
507
Benjamin Kramere003ca22015-10-28 13:54:16 +0000508namespace {
Eli Friedmanec52f922012-02-23 23:47:16 +0000509struct PragmaPackInfo {
Denis Zobnin10c4f452016-04-29 18:17:40 +0000510 Sema::PragmaMsStackAction Action;
511 StringRef SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +0000512 Token Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +0000513};
Benjamin Kramere003ca22015-10-28 13:54:16 +0000514} // end anonymous namespace
Eli Friedmanec52f922012-02-23 23:47:16 +0000515
516void Parser::HandlePragmaPack() {
517 assert(Tok.is(tok::annot_pragma_pack));
518 PragmaPackInfo *Info =
519 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
Alex Lorenz45b40142017-07-28 14:41:21 +0000520 SourceLocation PragmaLoc = Tok.getLocation();
Eli Friedman68be1642012-10-04 02:36:51 +0000521 ExprResult Alignment;
522 if (Info->Alignment.is(tok::numeric_constant)) {
523 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
Alex Lorenz45b40142017-07-28 14:41:21 +0000524 if (Alignment.isInvalid()) {
525 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000526 return;
Alex Lorenz45b40142017-07-28 14:41:21 +0000527 }
Eli Friedman68be1642012-10-04 02:36:51 +0000528 }
Denis Zobnin10c4f452016-04-29 18:17:40 +0000529 Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
530 Alignment.get());
Alex Lorenz45b40142017-07-28 14:41:21 +0000531 // Consume the token after processing the pragma to enable pragma-specific
532 // #include warnings.
533 ConsumeAnnotationToken();
Eli Friedmanec52f922012-02-23 23:47:16 +0000534}
535
Eli Friedman68be1642012-10-04 02:36:51 +0000536void Parser::HandlePragmaMSStruct() {
537 assert(Tok.is(tok::annot_pragma_msstruct));
Nico Weber779355f2016-03-02 23:22:00 +0000538 PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
539 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Eli Friedman68be1642012-10-04 02:36:51 +0000540 Actions.ActOnPragmaMSStruct(Kind);
Richard Smithaf3b3252017-05-18 19:21:48 +0000541 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000542}
543
544void Parser::HandlePragmaAlign() {
545 assert(Tok.is(tok::annot_pragma_align));
546 Sema::PragmaOptionsAlignKind Kind =
547 static_cast<Sema::PragmaOptionsAlignKind>(
548 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Alex Lorenz692821a2018-02-08 21:20:43 +0000549 Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation());
550 // Consume the token after processing the pragma to enable pragma-specific
551 // #include warnings.
552 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000553}
554
Richard Smithba3a4f92016-01-12 21:59:26 +0000555void Parser::HandlePragmaDump() {
556 assert(Tok.is(tok::annot_pragma_dump));
557 IdentifierInfo *II =
558 reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
559 Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
Richard Smithaf3b3252017-05-18 19:21:48 +0000560 ConsumeAnnotationToken();
Richard Smithba3a4f92016-01-12 21:59:26 +0000561}
562
Eli Friedman68be1642012-10-04 02:36:51 +0000563void Parser::HandlePragmaWeak() {
564 assert(Tok.is(tok::annot_pragma_weak));
Richard Smithaf3b3252017-05-18 19:21:48 +0000565 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000566 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
567 Tok.getLocation());
568 ConsumeToken(); // The weak name.
569}
570
571void Parser::HandlePragmaWeakAlias() {
572 assert(Tok.is(tok::annot_pragma_weakalias));
Richard Smithaf3b3252017-05-18 19:21:48 +0000573 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000574 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
575 SourceLocation WeakNameLoc = Tok.getLocation();
576 ConsumeToken();
577 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
578 SourceLocation AliasNameLoc = Tok.getLocation();
579 ConsumeToken();
580 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
581 WeakNameLoc, AliasNameLoc);
582
583}
584
585void Parser::HandlePragmaRedefineExtname() {
586 assert(Tok.is(tok::annot_pragma_redefine_extname));
Richard Smithaf3b3252017-05-18 19:21:48 +0000587 SourceLocation RedefLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000588 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
589 SourceLocation RedefNameLoc = Tok.getLocation();
590 ConsumeToken();
591 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
592 SourceLocation AliasNameLoc = Tok.getLocation();
593 ConsumeToken();
594 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
595 RedefNameLoc, AliasNameLoc);
596}
597
598void Parser::HandlePragmaFPContract() {
599 assert(Tok.is(tok::annot_pragma_fp_contract));
600 tok::OnOffSwitch OOS =
601 static_cast<tok::OnOffSwitch>(
602 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Adam Nemet60d32642017-04-04 21:18:36 +0000603
604 LangOptions::FPContractModeKind FPC;
605 switch (OOS) {
606 case tok::OOS_ON:
607 FPC = LangOptions::FPC_On;
608 break;
609 case tok::OOS_OFF:
610 FPC = LangOptions::FPC_Off;
611 break;
612 case tok::OOS_DEFAULT:
613 FPC = getLangOpts().getDefaultFPContractMode();
614 break;
615 }
616
617 Actions.ActOnPragmaFPContract(FPC);
Richard Smithaf3b3252017-05-18 19:21:48 +0000618 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000619}
620
Kevin P. Neal2c0bc8b2018-08-14 17:06:56 +0000621void Parser::HandlePragmaFEnvAccess() {
622 assert(Tok.is(tok::annot_pragma_fenv_access));
623 tok::OnOffSwitch OOS =
624 static_cast<tok::OnOffSwitch>(
625 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
626
627 LangOptions::FEnvAccessModeKind FPC;
628 switch (OOS) {
629 case tok::OOS_ON:
630 FPC = LangOptions::FEA_On;
631 break;
632 case tok::OOS_OFF:
633 FPC = LangOptions::FEA_Off;
634 break;
635 case tok::OOS_DEFAULT: // FIXME: Add this cli option when it makes sense.
636 FPC = LangOptions::FEA_Off;
637 break;
638 }
639
640 Actions.ActOnPragmaFEnvAccess(FPC);
641 ConsumeAnnotationToken();
642}
643
644
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000645StmtResult Parser::HandlePragmaCaptured()
646{
647 assert(Tok.is(tok::annot_pragma_captured));
Richard Smithaf3b3252017-05-18 19:21:48 +0000648 ConsumeAnnotationToken();
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000649
650 if (Tok.isNot(tok::l_brace)) {
Alp Tokerec543272013-12-24 09:48:30 +0000651 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000652 return StmtError();
653 }
654
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000655 SourceLocation Loc = Tok.getLocation();
656
Momchil Velikov57c681f2017-08-10 15:43:06 +0000657 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |
658 Scope::CompoundStmtScope);
Ben Langmuir37943a72013-05-03 19:00:33 +0000659 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
660 /*NumParams=*/1);
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000661
662 StmtResult R = ParseCompoundStatement();
663 CapturedRegionScope.Exit();
664
665 if (R.isInvalid()) {
666 Actions.ActOnCapturedRegionError();
667 return StmtError();
668 }
669
670 return Actions.ActOnCapturedRegionEnd(R.get());
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000671}
672
Eli Friedman68be1642012-10-04 02:36:51 +0000673namespace {
Yaxun Liu5b746652016-12-18 05:18:55 +0000674 enum OpenCLExtState : char {
675 Disable, Enable, Begin, End
676 };
677 typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
Eli Friedman68be1642012-10-04 02:36:51 +0000678}
679
680void Parser::HandlePragmaOpenCLExtension() {
681 assert(Tok.is(tok::annot_pragma_opencl_extension));
Yaxun Liu5b746652016-12-18 05:18:55 +0000682 OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
683 auto State = Data->second;
684 auto Ident = Data->first;
Eli Friedman68be1642012-10-04 02:36:51 +0000685 SourceLocation NameLoc = Tok.getLocation();
Richard Smithaf3b3252017-05-18 19:21:48 +0000686 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000687
Yaxun Liu5b746652016-12-18 05:18:55 +0000688 auto &Opt = Actions.getOpenCLOptions();
689 auto Name = Ident->getName();
Eli Friedman68be1642012-10-04 02:36:51 +0000690 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
691 // overriding all previously issued extension directives, but only if the
692 // behavior is set to disable."
Yaxun Liu5b746652016-12-18 05:18:55 +0000693 if (Name == "all") {
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000694 if (State == Disable) {
Yaxun Liu5b746652016-12-18 05:18:55 +0000695 Opt.disableAll();
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000696 Opt.enableSupportedCore(getLangOpts().OpenCLVersion);
697 } else {
Yaxun Liu5b746652016-12-18 05:18:55 +0000698 PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000699 }
Yaxun Liu5b746652016-12-18 05:18:55 +0000700 } else if (State == Begin) {
701 if (!Opt.isKnown(Name) ||
702 !Opt.isSupported(Name, getLangOpts().OpenCLVersion)) {
703 Opt.support(Name);
704 }
705 Actions.setCurrentOpenCLExtension(Name);
706 } else if (State == End) {
707 if (Name != Actions.getCurrentOpenCLExtension())
708 PP.Diag(NameLoc, diag::warn_pragma_begin_end_mismatch);
709 Actions.setCurrentOpenCLExtension("");
710 } else if (!Opt.isKnown(Name))
711 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
712 else if (Opt.isSupportedExtension(Name, getLangOpts().OpenCLVersion))
713 Opt.enable(Name, State == Enable);
714 else if (Opt.isSupportedCore(Name, getLangOpts().OpenCLVersion))
715 PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
716 else
717 PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
Eli Friedman68be1642012-10-04 02:36:51 +0000718}
719
David Majnemer4bb09802014-02-10 19:50:15 +0000720void Parser::HandlePragmaMSPointersToMembers() {
721 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
David Majnemer86c318f2014-02-11 21:05:00 +0000722 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
723 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
David Majnemer4bb09802014-02-10 19:50:15 +0000724 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Richard Smithaf3b3252017-05-18 19:21:48 +0000725 SourceLocation PragmaLoc = ConsumeAnnotationToken();
David Majnemer4bb09802014-02-10 19:50:15 +0000726 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
727}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000728
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000729void Parser::HandlePragmaMSVtorDisp() {
730 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
731 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
Denis Zobnin2290dac2016-04-29 11:27:00 +0000732 Sema::PragmaMsStackAction Action =
733 static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000734 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
Richard Smithaf3b3252017-05-18 19:21:48 +0000735 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Denis Zobnin2290dac2016-04-29 11:27:00 +0000736 Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000737}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000738
Warren Huntc3b18962014-04-08 22:30:47 +0000739void Parser::HandlePragmaMSPragma() {
740 assert(Tok.is(tok::annot_pragma_ms_pragma));
741 // Grab the tokens out of the annotation and enter them into the stream.
David Blaikie2eabcc92016-02-09 18:52:09 +0000742 auto TheTokens =
743 (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
744 PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true);
Richard Smithaf3b3252017-05-18 19:21:48 +0000745 SourceLocation PragmaLocation = ConsumeAnnotationToken();
Warren Huntc3b18962014-04-08 22:30:47 +0000746 assert(Tok.isAnyIdentifier());
Reid Kleckner722b1df2014-07-18 00:13:16 +0000747 StringRef PragmaName = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000748 PP.Lex(Tok); // pragma kind
Reid Kleckner722b1df2014-07-18 00:13:16 +0000749
Warren Huntc3b18962014-04-08 22:30:47 +0000750 // Figure out which #pragma we're dealing with. The switch has no default
751 // because lex shouldn't emit the annotation token for unrecognized pragmas.
Reid Kleckner722b1df2014-07-18 00:13:16 +0000752 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
Warren Huntc3b18962014-04-08 22:30:47 +0000753 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
754 .Case("data_seg", &Parser::HandlePragmaMSSegment)
755 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
756 .Case("const_seg", &Parser::HandlePragmaMSSegment)
757 .Case("code_seg", &Parser::HandlePragmaMSSegment)
758 .Case("section", &Parser::HandlePragmaMSSection)
759 .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000760
761 if (!(this->*Handler)(PragmaName, PragmaLocation)) {
762 // Pragma handling failed, and has been diagnosed. Slurp up the tokens
763 // until eof (really end of line) to prevent follow-on errors.
Warren Huntc3b18962014-04-08 22:30:47 +0000764 while (Tok.isNot(tok::eof))
765 PP.Lex(Tok);
766 PP.Lex(Tok);
767 }
768}
769
Reid Kleckner722b1df2014-07-18 00:13:16 +0000770bool Parser::HandlePragmaMSSection(StringRef PragmaName,
771 SourceLocation PragmaLocation) {
772 if (Tok.isNot(tok::l_paren)) {
773 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
774 return false;
775 }
Warren Huntc3b18962014-04-08 22:30:47 +0000776 PP.Lex(Tok); // (
777 // Parsing code for pragma section
Reid Kleckner722b1df2014-07-18 00:13:16 +0000778 if (Tok.isNot(tok::string_literal)) {
779 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
780 << PragmaName;
781 return false;
782 }
783 ExprResult StringResult = ParseStringLiteralExpression();
784 if (StringResult.isInvalid())
785 return false; // Already diagnosed.
786 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
787 if (SegmentName->getCharByteWidth() != 1) {
788 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
789 << PragmaName;
790 return false;
791 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000792 int SectionFlags = ASTContext::PSF_Read;
793 bool SectionFlagsAreDefault = true;
Warren Huntc3b18962014-04-08 22:30:47 +0000794 while (Tok.is(tok::comma)) {
795 PP.Lex(Tok); // ,
David Majnemer48c28fa2014-10-22 21:08:43 +0000796 // Ignore "long" and "short".
797 // They are undocumented, but widely used, section attributes which appear
798 // to do nothing.
799 if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
800 PP.Lex(Tok); // long/short
801 continue;
802 }
803
Reid Kleckner722b1df2014-07-18 00:13:16 +0000804 if (!Tok.isAnyIdentifier()) {
805 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
806 << PragmaName;
807 return false;
808 }
Hans Wennborg899ded92014-10-16 20:52:46 +0000809 ASTContext::PragmaSectionFlag Flag =
810 llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
Warren Huntc3b18962014-04-08 22:30:47 +0000811 Tok.getIdentifierInfo()->getName())
Hans Wennborg899ded92014-10-16 20:52:46 +0000812 .Case("read", ASTContext::PSF_Read)
813 .Case("write", ASTContext::PSF_Write)
814 .Case("execute", ASTContext::PSF_Execute)
815 .Case("shared", ASTContext::PSF_Invalid)
816 .Case("nopage", ASTContext::PSF_Invalid)
817 .Case("nocache", ASTContext::PSF_Invalid)
818 .Case("discard", ASTContext::PSF_Invalid)
819 .Case("remove", ASTContext::PSF_Invalid)
820 .Default(ASTContext::PSF_None);
821 if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
822 PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
Reid Kleckner722b1df2014-07-18 00:13:16 +0000823 ? diag::warn_pragma_invalid_specific_action
824 : diag::warn_pragma_unsupported_action)
Warren Huntc3b18962014-04-08 22:30:47 +0000825 << PragmaName << Tok.getIdentifierInfo()->getName();
Reid Kleckner722b1df2014-07-18 00:13:16 +0000826 return false;
Warren Huntc3b18962014-04-08 22:30:47 +0000827 }
828 SectionFlags |= Flag;
David Majnemer48c28fa2014-10-22 21:08:43 +0000829 SectionFlagsAreDefault = false;
Warren Huntc3b18962014-04-08 22:30:47 +0000830 PP.Lex(Tok); // Identifier
831 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000832 // If no section attributes are specified, the section will be marked as
833 // read/write.
834 if (SectionFlagsAreDefault)
835 SectionFlags |= ASTContext::PSF_Write;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000836 if (Tok.isNot(tok::r_paren)) {
837 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
838 return false;
839 }
Warren Huntc3b18962014-04-08 22:30:47 +0000840 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000841 if (Tok.isNot(tok::eof)) {
842 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
843 << PragmaName;
844 return false;
845 }
Warren Huntc3b18962014-04-08 22:30:47 +0000846 PP.Lex(Tok); // eof
847 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000848 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000849}
850
Reid Kleckner722b1df2014-07-18 00:13:16 +0000851bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
852 SourceLocation PragmaLocation) {
853 if (Tok.isNot(tok::l_paren)) {
854 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
855 return false;
856 }
Warren Huntc3b18962014-04-08 22:30:47 +0000857 PP.Lex(Tok); // (
858 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000859 StringRef SlotLabel;
Warren Huntc3b18962014-04-08 22:30:47 +0000860 if (Tok.isAnyIdentifier()) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000861 StringRef PushPop = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000862 if (PushPop == "push")
863 Action = Sema::PSK_Push;
864 else if (PushPop == "pop")
865 Action = Sema::PSK_Pop;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000866 else {
867 PP.Diag(PragmaLocation,
868 diag::warn_pragma_expected_section_push_pop_or_name)
869 << PragmaName;
870 return false;
871 }
Warren Huntc3b18962014-04-08 22:30:47 +0000872 if (Action != Sema::PSK_Reset) {
873 PP.Lex(Tok); // push | pop
874 if (Tok.is(tok::comma)) {
875 PP.Lex(Tok); // ,
876 // If we've got a comma, we either need a label or a string.
877 if (Tok.isAnyIdentifier()) {
878 SlotLabel = Tok.getIdentifierInfo()->getName();
879 PP.Lex(Tok); // identifier
880 if (Tok.is(tok::comma))
881 PP.Lex(Tok);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000882 else if (Tok.isNot(tok::r_paren)) {
883 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
884 << PragmaName;
885 return false;
886 }
Warren Huntc3b18962014-04-08 22:30:47 +0000887 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000888 } else if (Tok.isNot(tok::r_paren)) {
889 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
890 return false;
891 }
Warren Huntc3b18962014-04-08 22:30:47 +0000892 }
893 }
894 // Grab the string literal for our section name.
895 StringLiteral *SegmentName = nullptr;
896 if (Tok.isNot(tok::r_paren)) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000897 if (Tok.isNot(tok::string_literal)) {
898 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
Warren Huntc3b18962014-04-08 22:30:47 +0000899 diag::warn_pragma_expected_section_name :
900 diag::warn_pragma_expected_section_label_or_name :
901 diag::warn_pragma_expected_section_push_pop_or_name;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000902 PP.Diag(PragmaLocation, DiagID) << PragmaName;
903 return false;
904 }
905 ExprResult StringResult = ParseStringLiteralExpression();
906 if (StringResult.isInvalid())
907 return false; // Already diagnosed.
908 SegmentName = cast<StringLiteral>(StringResult.get());
909 if (SegmentName->getCharByteWidth() != 1) {
910 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
911 << PragmaName;
912 return false;
913 }
Warren Huntc3b18962014-04-08 22:30:47 +0000914 // Setting section "" has no effect
915 if (SegmentName->getLength())
916 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
917 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000918 if (Tok.isNot(tok::r_paren)) {
919 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
920 return false;
921 }
Warren Huntc3b18962014-04-08 22:30:47 +0000922 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000923 if (Tok.isNot(tok::eof)) {
924 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
925 << PragmaName;
926 return false;
927 }
Warren Huntc3b18962014-04-08 22:30:47 +0000928 PP.Lex(Tok); // eof
929 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
930 SegmentName, PragmaName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000931 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000932}
933
Reid Kleckner1a711b12014-07-22 00:53:05 +0000934// #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000935bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
936 SourceLocation PragmaLocation) {
David Majnemerad2986e2014-08-14 06:35:08 +0000937 if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
938 PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
939 return false;
940 }
941
Reid Kleckner1a711b12014-07-22 00:53:05 +0000942 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
943 PragmaName))
944 return false;
945
946 // Parse either the known section names or the string section name.
947 StringLiteral *SegmentName = nullptr;
948 if (Tok.isAnyIdentifier()) {
949 auto *II = Tok.getIdentifierInfo();
950 StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
951 .Case("compiler", "\".CRT$XCC\"")
952 .Case("lib", "\".CRT$XCL\"")
953 .Case("user", "\".CRT$XCU\"")
954 .Default("");
955
956 if (!Section.empty()) {
957 // Pretend the user wrote the appropriate string literal here.
958 Token Toks[1];
959 Toks[0].startToken();
960 Toks[0].setKind(tok::string_literal);
961 Toks[0].setLocation(Tok.getLocation());
962 Toks[0].setLiteralData(Section.data());
963 Toks[0].setLength(Section.size());
964 SegmentName =
965 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
966 PP.Lex(Tok);
967 }
968 } else if (Tok.is(tok::string_literal)) {
969 ExprResult StringResult = ParseStringLiteralExpression();
970 if (StringResult.isInvalid())
971 return false;
972 SegmentName = cast<StringLiteral>(StringResult.get());
973 if (SegmentName->getCharByteWidth() != 1) {
974 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
975 << PragmaName;
976 return false;
977 }
978 // FIXME: Add support for the '[, func-name]' part of the pragma.
979 }
980
981 if (!SegmentName) {
982 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
983 return false;
984 }
985
986 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
987 PragmaName) ||
988 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
989 PragmaName))
990 return false;
991
992 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
993 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +0000994}
995
Benjamin Kramere003ca22015-10-28 13:54:16 +0000996namespace {
Eli Bendersky06a40422014-06-06 20:31:48 +0000997struct PragmaLoopHintInfo {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000998 Token PragmaName;
Eli Bendersky06a40422014-06-06 20:31:48 +0000999 Token Option;
Benjamin Kramerfa7f8552015-08-05 09:39:57 +00001000 ArrayRef<Token> Toks;
Eli Bendersky06a40422014-06-06 20:31:48 +00001001};
Benjamin Kramere003ca22015-10-28 13:54:16 +00001002} // end anonymous namespace
Eli Bendersky06a40422014-06-06 20:31:48 +00001003
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001004static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
1005 std::string PragmaString;
1006 if (PragmaName.getIdentifierInfo()->getName() == "loop") {
1007 PragmaString = "clang loop ";
1008 PragmaString += Option.getIdentifierInfo()->getName();
David Greenc8e39242018-08-01 14:36:12 +00001009 } else if (PragmaName.getIdentifierInfo()->getName() == "unroll_and_jam") {
1010 PragmaString = "unroll_and_jam";
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001011 } else {
1012 assert(PragmaName.getIdentifierInfo()->getName() == "unroll" &&
1013 "Unexpected pragma name");
1014 PragmaString = "unroll";
1015 }
1016 return PragmaString;
1017}
1018
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001019bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
Eli Bendersky06a40422014-06-06 20:31:48 +00001020 assert(Tok.is(tok::annot_pragma_loop_hint));
1021 PragmaLoopHintInfo *Info =
1022 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
1023
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001024 IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
1025 Hint.PragmaNameLoc = IdentifierLoc::create(
1026 Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
Eli Bendersky06a40422014-06-06 20:31:48 +00001027
Aaron Ballmanef940aa2014-07-31 21:24:32 +00001028 // It is possible that the loop hint has no option identifier, such as
1029 // #pragma unroll(4).
1030 IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
1031 ? Info->Option.getIdentifierInfo()
1032 : nullptr;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001033 Hint.OptionLoc = IdentifierLoc::create(
1034 Actions.Context, Info->Option.getLocation(), OptionInfo);
1035
David Blaikie2eabcc92016-02-09 18:52:09 +00001036 llvm::ArrayRef<Token> Toks = Info->Toks;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001037
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001038 // Return a valid hint if pragma unroll or nounroll were specified
1039 // without an argument.
1040 bool PragmaUnroll = PragmaNameInfo->getName() == "unroll";
1041 bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll";
David Greenc8e39242018-08-01 14:36:12 +00001042 bool PragmaUnrollAndJam = PragmaNameInfo->getName() == "unroll_and_jam";
1043 bool PragmaNoUnrollAndJam = PragmaNameInfo->getName() == "nounroll_and_jam";
1044 if (Toks.empty() && (PragmaUnroll || PragmaNoUnroll || PragmaUnrollAndJam ||
1045 PragmaNoUnrollAndJam)) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001046 ConsumeAnnotationToken();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001047 Hint.Range = Info->PragmaName.getLocation();
1048 return true;
1049 }
1050
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001051 // The constant expression is always followed by an eof token, which increases
1052 // the TokSize by 1.
David Blaikie2eabcc92016-02-09 18:52:09 +00001053 assert(!Toks.empty() &&
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001054 "PragmaLoopHintInfo::Toks must contain at least one token.");
1055
1056 // If no option is specified the argument is assumed to be a constant expr.
Tyler Nowicki24853c12015-06-08 23:13:43 +00001057 bool OptionUnroll = false;
David Greenc8e39242018-08-01 14:36:12 +00001058 bool OptionUnrollAndJam = false;
Adam Nemet2de463e2016-06-14 12:04:26 +00001059 bool OptionDistribute = 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");
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001065 StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
1066 .Case("vectorize", true)
1067 .Case("interleave", true)
Adam Nemet2de463e2016-06-14 12:04:26 +00001068 .Default(false) ||
David Greenc8e39242018-08-01 14:36:12 +00001069 OptionUnroll || OptionUnrollAndJam || OptionDistribute;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001070 }
1071
David Greenc8e39242018-08-01 14:36:12 +00001072 bool AssumeSafetyArg =
1073 !OptionUnroll && !OptionUnrollAndJam && !OptionDistribute;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001074 // Verify loop hint has an argument.
1075 if (Toks[0].is(tok::eof)) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001076 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001077 Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
David Greenc8e39242018-08-01 14:36:12 +00001078 << /*StateArgument=*/StateOption
1079 << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
Adam Nemet2de463e2016-06-14 12:04:26 +00001080 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001081 return false;
1082 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001083
1084 // Validate the argument.
1085 if (StateOption) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001086 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001087 SourceLocation StateLoc = Toks[0].getLocation();
1088 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
Adam Nemet50de4e82016-04-19 22:17:45 +00001089
David Greenc8e39242018-08-01 14:36:12 +00001090 bool Valid =
1091 StateInfo && llvm::StringSwitch<bool>(StateInfo->getName())
1092 .Cases("enable", "disable", true)
1093 .Case("full", OptionUnroll || OptionUnrollAndJam)
1094 .Case("assume_safety", AssumeSafetyArg)
1095 .Default(false);
Adam Nemet50de4e82016-04-19 22:17:45 +00001096 if (!Valid) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001097 Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
David Greenc8e39242018-08-01 14:36:12 +00001098 << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
Adam Nemet2de463e2016-06-14 12:04:26 +00001099 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001100 return false;
1101 }
David Blaikie2eabcc92016-02-09 18:52:09 +00001102 if (Toks.size() > 2)
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001103 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1104 << PragmaLoopHintString(Info->PragmaName, Info->Option);
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001105 Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1106 } else {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001107 // Enter constant expression including eof terminator into token stream.
David Blaikie2eabcc92016-02-09 18:52:09 +00001108 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false);
Richard Smithaf3b3252017-05-18 19:21:48 +00001109 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001110
1111 ExprResult R = ParseConstantExpression();
1112
1113 // Tokens following an error in an ill-formed constant expression will
1114 // remain in the token stream and must be removed.
1115 if (Tok.isNot(tok::eof)) {
1116 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1117 << PragmaLoopHintString(Info->PragmaName, Info->Option);
1118 while (Tok.isNot(tok::eof))
1119 ConsumeAnyToken();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001120 }
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001121
1122 ConsumeToken(); // Consume the constant expression eof terminator.
1123
1124 if (R.isInvalid() ||
1125 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
1126 return false;
1127
1128 // Argument is a constant expression with an integer type.
1129 Hint.ValueExpr = R.get();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001130 }
Eli Bendersky06a40422014-06-06 20:31:48 +00001131
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001132 Hint.Range = SourceRange(Info->PragmaName.getLocation(),
David Blaikie2eabcc92016-02-09 18:52:09 +00001133 Info->Toks.back().getLocation());
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001134 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +00001135}
1136
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001137namespace {
1138struct PragmaAttributeInfo {
Erik Pilkington7d180942018-10-29 17:38:42 +00001139 enum ActionType { Push, Pop, Attribute };
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001140 ParsedAttributes &Attributes;
1141 ActionType Action;
Erik Pilkington0876cae2018-12-20 22:32:04 +00001142 const IdentifierInfo *Namespace = nullptr;
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001143 ArrayRef<Token> Tokens;
1144
1145 PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
1146};
1147
1148#include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
1149
1150} // end anonymous namespace
1151
1152static StringRef getIdentifier(const Token &Tok) {
1153 if (Tok.is(tok::identifier))
1154 return Tok.getIdentifierInfo()->getName();
1155 const char *S = tok::getKeywordSpelling(Tok.getKind());
1156 if (!S)
1157 return "";
1158 return S;
1159}
1160
1161static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) {
1162 using namespace attr;
1163 switch (Rule) {
1164#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \
1165 case Value: \
1166 return IsAbstract;
1167#include "clang/Basic/AttrSubMatchRulesList.inc"
1168 }
1169 llvm_unreachable("Invalid attribute subject match rule");
1170 return false;
1171}
1172
1173static void diagnoseExpectedAttributeSubjectSubRule(
1174 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1175 SourceLocation SubRuleLoc) {
1176 auto Diagnostic =
1177 PRef.Diag(SubRuleLoc,
1178 diag::err_pragma_attribute_expected_subject_sub_identifier)
1179 << PrimaryRuleName;
1180 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1181 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1182 else
1183 Diagnostic << /*SubRulesSupported=*/0;
1184}
1185
1186static void diagnoseUnknownAttributeSubjectSubRule(
1187 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1188 StringRef SubRuleName, SourceLocation SubRuleLoc) {
1189
1190 auto Diagnostic =
1191 PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)
1192 << SubRuleName << PrimaryRuleName;
1193 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1194 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1195 else
1196 Diagnostic << /*SubRulesSupported=*/0;
1197}
1198
1199bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
1200 attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,
1201 SourceLocation &LastMatchRuleEndLoc) {
1202 bool IsAny = false;
1203 BalancedDelimiterTracker AnyParens(*this, tok::l_paren);
1204 if (getIdentifier(Tok) == "any") {
1205 AnyLoc = ConsumeToken();
1206 IsAny = true;
1207 if (AnyParens.expectAndConsume())
1208 return true;
1209 }
1210
1211 do {
1212 // Parse the subject matcher rule.
1213 StringRef Name = getIdentifier(Tok);
1214 if (Name.empty()) {
1215 Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);
1216 return true;
1217 }
1218 std::pair<Optional<attr::SubjectMatchRule>,
1219 Optional<attr::SubjectMatchRule> (*)(StringRef, bool)>
1220 Rule = isAttributeSubjectMatchRule(Name);
1221 if (!Rule.first) {
1222 Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;
1223 return true;
1224 }
1225 attr::SubjectMatchRule PrimaryRule = *Rule.first;
1226 SourceLocation RuleLoc = ConsumeToken();
1227
1228 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1229 if (isAbstractAttrMatcherRule(PrimaryRule)) {
1230 if (Parens.expectAndConsume())
1231 return true;
1232 } else if (Parens.consumeOpen()) {
1233 if (!SubjectMatchRules
1234 .insert(
1235 std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))
1236 .second)
1237 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1238 << Name
1239 << FixItHint::CreateRemoval(SourceRange(
1240 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc));
1241 LastMatchRuleEndLoc = RuleLoc;
1242 continue;
1243 }
1244
1245 // Parse the sub-rules.
1246 StringRef SubRuleName = getIdentifier(Tok);
1247 if (SubRuleName.empty()) {
1248 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1249 Tok.getLocation());
1250 return true;
1251 }
1252 attr::SubjectMatchRule SubRule;
1253 if (SubRuleName == "unless") {
1254 SourceLocation SubRuleLoc = ConsumeToken();
1255 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1256 if (Parens.expectAndConsume())
1257 return true;
1258 SubRuleName = getIdentifier(Tok);
1259 if (SubRuleName.empty()) {
1260 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1261 SubRuleLoc);
1262 return true;
1263 }
1264 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);
1265 if (!SubRuleOrNone) {
1266 std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";
1267 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1268 SubRuleUnlessName, SubRuleLoc);
1269 return true;
1270 }
1271 SubRule = *SubRuleOrNone;
1272 ConsumeToken();
1273 if (Parens.consumeClose())
1274 return true;
1275 } else {
1276 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);
1277 if (!SubRuleOrNone) {
1278 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1279 SubRuleName, Tok.getLocation());
1280 return true;
1281 }
1282 SubRule = *SubRuleOrNone;
1283 ConsumeToken();
1284 }
1285 SourceLocation RuleEndLoc = Tok.getLocation();
1286 LastMatchRuleEndLoc = RuleEndLoc;
1287 if (Parens.consumeClose())
1288 return true;
1289 if (!SubjectMatchRules
1290 .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))
1291 .second) {
1292 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1293 << attr::getSubjectMatchRuleSpelling(SubRule)
1294 << FixItHint::CreateRemoval(SourceRange(
1295 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc));
1296 continue;
1297 }
1298 } while (IsAny && TryConsumeToken(tok::comma));
1299
1300 if (IsAny)
1301 if (AnyParens.consumeClose())
1302 return true;
1303
1304 return false;
1305}
1306
1307namespace {
1308
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00001309/// Describes the stage at which attribute subject rule parsing was interrupted.
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001310enum class MissingAttributeSubjectRulesRecoveryPoint {
1311 Comma,
1312 ApplyTo,
1313 Equals,
1314 Any,
1315 None,
1316};
1317
1318MissingAttributeSubjectRulesRecoveryPoint
1319getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
1320 if (const auto *II = Tok.getIdentifierInfo()) {
1321 if (II->isStr("apply_to"))
1322 return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
1323 if (II->isStr("any"))
1324 return MissingAttributeSubjectRulesRecoveryPoint::Any;
1325 }
1326 if (Tok.is(tok::equal))
1327 return MissingAttributeSubjectRulesRecoveryPoint::Equals;
1328 return MissingAttributeSubjectRulesRecoveryPoint::None;
1329}
1330
1331/// Creates a diagnostic for the attribute subject rule parsing diagnostic that
1332/// suggests the possible attribute subject rules in a fix-it together with
1333/// any other missing tokens.
1334DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
Erich Keanee891aa92018-07-13 15:07:47 +00001335 unsigned DiagID, ParsedAttr &Attribute,
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001336 MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
1337 SourceLocation Loc = PRef.getEndOfPreviousToken();
1338 if (Loc.isInvalid())
1339 Loc = PRef.getCurToken().getLocation();
1340 auto Diagnostic = PRef.Diag(Loc, DiagID);
1341 std::string FixIt;
1342 MissingAttributeSubjectRulesRecoveryPoint EndPoint =
1343 getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());
1344 if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)
1345 FixIt = ", ";
1346 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&
1347 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo)
1348 FixIt += "apply_to";
1349 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&
1350 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)
1351 FixIt += " = ";
1352 SourceRange FixItRange(Loc);
1353 if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
1354 // Gather the subject match rules that are supported by the attribute.
1355 SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> SubjectMatchRuleSet;
1356 Attribute.getMatchRules(PRef.getLangOpts(), SubjectMatchRuleSet);
1357 if (SubjectMatchRuleSet.empty()) {
1358 // FIXME: We can emit a "fix-it" with a subject list placeholder when
1359 // placeholders will be supported by the fix-its.
1360 return Diagnostic;
1361 }
1362 FixIt += "any(";
1363 bool NeedsComma = false;
1364 for (const auto &I : SubjectMatchRuleSet) {
1365 // Ensure that the missing rule is reported in the fix-it only when it's
1366 // supported in the current language mode.
1367 if (!I.second)
1368 continue;
1369 if (NeedsComma)
1370 FixIt += ", ";
1371 else
1372 NeedsComma = true;
1373 FixIt += attr::getSubjectMatchRuleSpelling(I.first);
1374 }
1375 FixIt += ")";
1376 // Check if we need to remove the range
1377 PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);
1378 FixItRange.setEnd(PRef.getCurToken().getLocation());
1379 }
1380 if (FixItRange.getBegin() == FixItRange.getEnd())
1381 Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);
1382 else
1383 Diagnostic << FixItHint::CreateReplacement(
1384 CharSourceRange::getCharRange(FixItRange), FixIt);
1385 return Diagnostic;
1386}
1387
1388} // end anonymous namespace
1389
1390void Parser::HandlePragmaAttribute() {
1391 assert(Tok.is(tok::annot_pragma_attribute) &&
1392 "Expected #pragma attribute annotation token");
1393 SourceLocation PragmaLoc = Tok.getLocation();
1394 auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
1395 if (Info->Action == PragmaAttributeInfo::Pop) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001396 ConsumeAnnotationToken();
Erik Pilkington0876cae2018-12-20 22:32:04 +00001397 Actions.ActOnPragmaAttributePop(PragmaLoc, Info->Namespace);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001398 return;
1399 }
1400 // Parse the actual attribute with its arguments.
Erik Pilkington7d180942018-10-29 17:38:42 +00001401 assert((Info->Action == PragmaAttributeInfo::Push ||
1402 Info->Action == PragmaAttributeInfo::Attribute) &&
Erik Pilkingtonb287a012018-10-29 03:24:16 +00001403 "Unexpected #pragma attribute command");
Erik Pilkington7d180942018-10-29 17:38:42 +00001404
1405 if (Info->Action == PragmaAttributeInfo::Push && Info->Tokens.empty()) {
1406 ConsumeAnnotationToken();
Erik Pilkington0876cae2018-12-20 22:32:04 +00001407 Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
Erik Pilkington7d180942018-10-29 17:38:42 +00001408 return;
1409 }
1410
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001411 PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false);
Richard Smithaf3b3252017-05-18 19:21:48 +00001412 ConsumeAnnotationToken();
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001413
1414 ParsedAttributes &Attrs = Info->Attributes;
1415 Attrs.clearListOnly();
1416
1417 auto SkipToEnd = [this]() {
1418 SkipUntil(tok::eof, StopBeforeMatch);
1419 ConsumeToken();
1420 };
1421
1422 if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) {
1423 // Parse the CXX11 style attribute.
1424 ParseCXX11AttributeSpecifier(Attrs);
1425 } else if (Tok.is(tok::kw___attribute)) {
1426 ConsumeToken();
1427 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
1428 "attribute"))
1429 return SkipToEnd();
1430 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))
1431 return SkipToEnd();
1432
1433 if (Tok.isNot(tok::identifier)) {
1434 Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);
1435 SkipToEnd();
1436 return;
1437 }
1438 IdentifierInfo *AttrName = Tok.getIdentifierInfo();
1439 SourceLocation AttrNameLoc = ConsumeToken();
1440
1441 if (Tok.isNot(tok::l_paren))
1442 Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
Erich Keanee891aa92018-07-13 15:07:47 +00001443 ParsedAttr::AS_GNU);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001444 else
1445 ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
1446 /*ScopeName=*/nullptr,
Erich Keanee891aa92018-07-13 15:07:47 +00001447 /*ScopeLoc=*/SourceLocation(), ParsedAttr::AS_GNU,
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001448 /*Declarator=*/nullptr);
1449
1450 if (ExpectAndConsume(tok::r_paren))
1451 return SkipToEnd();
1452 if (ExpectAndConsume(tok::r_paren))
1453 return SkipToEnd();
1454 } else if (Tok.is(tok::kw___declspec)) {
1455 ParseMicrosoftDeclSpecs(Attrs);
1456 } else {
1457 Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
1458 if (Tok.getIdentifierInfo()) {
1459 // If we suspect that this is an attribute suggest the use of
1460 // '__attribute__'.
Erich Keanee891aa92018-07-13 15:07:47 +00001461 if (ParsedAttr::getKind(Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
1462 ParsedAttr::AS_GNU) !=
1463 ParsedAttr::UnknownAttribute) {
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001464 SourceLocation InsertStartLoc = Tok.getLocation();
1465 ConsumeToken();
1466 if (Tok.is(tok::l_paren)) {
1467 ConsumeAnyToken();
1468 SkipUntil(tok::r_paren, StopBeforeMatch);
1469 if (Tok.isNot(tok::r_paren))
1470 return SkipToEnd();
1471 }
1472 Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)
1473 << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")
1474 << FixItHint::CreateInsertion(Tok.getEndLoc(), "))");
1475 }
1476 }
1477 SkipToEnd();
1478 return;
1479 }
1480
Erich Keanec480f302018-07-12 21:09:05 +00001481 if (Attrs.empty() || Attrs.begin()->isInvalid()) {
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001482 SkipToEnd();
1483 return;
1484 }
1485
1486 // Ensure that we don't have more than one attribute.
Erich Keanec480f302018-07-12 21:09:05 +00001487 if (Attrs.size() > 1) {
1488 SourceLocation Loc = Attrs[1].getLoc();
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001489 Diag(Loc, diag::err_pragma_attribute_multiple_attributes);
1490 SkipToEnd();
1491 return;
1492 }
1493
Erich Keanee891aa92018-07-13 15:07:47 +00001494 ParsedAttr &Attribute = *Attrs.begin();
Erich Keanec480f302018-07-12 21:09:05 +00001495 if (!Attribute.isSupportedByPragmaAttribute()) {
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001496 Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
Erich Keanec480f302018-07-12 21:09:05 +00001497 << Attribute.getName();
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001498 SkipToEnd();
1499 return;
1500 }
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001501
1502 // Parse the subject-list.
1503 if (!TryConsumeToken(tok::comma)) {
1504 createExpectedAttributeSubjectRulesTokenDiagnostic(
1505 diag::err_expected, Attribute,
1506 MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)
1507 << tok::comma;
1508 SkipToEnd();
1509 return;
1510 }
1511
1512 if (Tok.isNot(tok::identifier)) {
1513 createExpectedAttributeSubjectRulesTokenDiagnostic(
1514 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1515 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1516 SkipToEnd();
1517 return;
1518 }
1519 const IdentifierInfo *II = Tok.getIdentifierInfo();
1520 if (!II->isStr("apply_to")) {
1521 createExpectedAttributeSubjectRulesTokenDiagnostic(
1522 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1523 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1524 SkipToEnd();
1525 return;
1526 }
1527 ConsumeToken();
1528
1529 if (!TryConsumeToken(tok::equal)) {
1530 createExpectedAttributeSubjectRulesTokenDiagnostic(
1531 diag::err_expected, Attribute,
1532 MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)
1533 << tok::equal;
1534 SkipToEnd();
1535 return;
1536 }
1537
1538 attr::ParsedSubjectMatchRuleSet SubjectMatchRules;
1539 SourceLocation AnyLoc, LastMatchRuleEndLoc;
1540 if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,
1541 LastMatchRuleEndLoc)) {
1542 SkipToEnd();
1543 return;
1544 }
1545
1546 // Tokens following an ill-formed attribute will remain in the token stream
1547 // and must be removed.
1548 if (Tok.isNot(tok::eof)) {
1549 Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
1550 SkipToEnd();
1551 return;
1552 }
1553
1554 // Consume the eof terminator token.
1555 ConsumeToken();
1556
Erik Pilkington7d180942018-10-29 17:38:42 +00001557 // Handle a mixed push/attribute by desurging to a push, then an attribute.
1558 if (Info->Action == PragmaAttributeInfo::Push)
Erik Pilkington0876cae2018-12-20 22:32:04 +00001559 Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
Erik Pilkington7d180942018-10-29 17:38:42 +00001560
1561 Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc,
1562 std::move(SubjectMatchRules));
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001563}
1564
Eli Bendersky06a40422014-06-06 20:31:48 +00001565// #pragma GCC visibility comes in two variants:
1566// 'push' '(' [visibility] ')'
1567// 'pop'
Fangrui Song6907ce22018-07-30 19:24:48 +00001568void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
Douglas Gregorc7d65762010-09-09 22:45:38 +00001569 PragmaIntroducerKind Introducer,
1570 Token &VisTok) {
Eli Friedman570024a2010-08-05 06:57:20 +00001571 SourceLocation VisLoc = VisTok.getLocation();
1572
1573 Token Tok;
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001574 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001575
1576 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
1577
Eli Friedman570024a2010-08-05 06:57:20 +00001578 const IdentifierInfo *VisType;
1579 if (PushPop && PushPop->isStr("pop")) {
Craig Topper161e4db2014-05-21 06:02:52 +00001580 VisType = nullptr;
Eli Friedman570024a2010-08-05 06:57:20 +00001581 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001582 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001583 if (Tok.isNot(tok::l_paren)) {
1584 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
1585 << "visibility";
1586 return;
1587 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001588 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001589 VisType = Tok.getIdentifierInfo();
1590 if (!VisType) {
1591 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1592 << "visibility";
1593 return;
1594 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001595 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001596 if (Tok.isNot(tok::r_paren)) {
1597 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
1598 << "visibility";
1599 return;
1600 }
1601 } else {
1602 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1603 << "visibility";
1604 return;
1605 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001606 SourceLocation EndLoc = Tok.getLocation();
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001607 PP.LexUnexpandedToken(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001608 if (Tok.isNot(tok::eod)) {
Eli Friedman570024a2010-08-05 06:57:20 +00001609 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1610 << "visibility";
1611 return;
1612 }
1613
David Blaikie2eabcc92016-02-09 18:52:09 +00001614 auto Toks = llvm::make_unique<Token[]>(1);
Rafael Espindola273fd772012-01-26 02:02:57 +00001615 Toks[0].startToken();
1616 Toks[0].setKind(tok::annot_pragma_vis);
1617 Toks[0].setLocation(VisLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001618 Toks[0].setAnnotationEndLoc(EndLoc);
Rafael Espindola273fd772012-01-26 02:02:57 +00001619 Toks[0].setAnnotationValue(
1620 const_cast<void*>(static_cast<const void*>(VisType)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001621 PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true);
Eli Friedman570024a2010-08-05 06:57:20 +00001622}
1623
Daniel Dunbar921b9682008-10-04 19:21:03 +00001624// #pragma pack(...) comes in the following delicious flavors:
1625// pack '(' [integer] ')'
1626// pack '(' 'show' ')'
1627// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Fangrui Song6907ce22018-07-30 19:24:48 +00001628void PragmaPackHandler::HandlePragma(Preprocessor &PP,
Douglas Gregorc7d65762010-09-09 22:45:38 +00001629 PragmaIntroducerKind Introducer,
1630 Token &PackTok) {
Daniel Dunbar921b9682008-10-04 19:21:03 +00001631 SourceLocation PackLoc = PackTok.getLocation();
1632
1633 Token Tok;
1634 PP.Lex(Tok);
1635 if (Tok.isNot(tok::l_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001636 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001637 return;
1638 }
1639
Denis Zobnin10c4f452016-04-29 18:17:40 +00001640 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
1641 StringRef SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001642 Token Alignment;
1643 Alignment.startToken();
Mike Stump11289f42009-09-09 15:08:12 +00001644 PP.Lex(Tok);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001645 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +00001646 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001647
1648 PP.Lex(Tok);
Eli Friedman055c9702011-11-02 01:53:16 +00001649
1650 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
1651 // the push/pop stack.
1652 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
Denis Zobnin10c4f452016-04-29 18:17:40 +00001653 Action =
1654 PP.getLangOpts().ApplePragmaPack ? Sema::PSK_Push_Set : Sema::PSK_Set;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001655 } else if (Tok.is(tok::identifier)) {
1656 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattnere3d20d92008-11-23 21:45:46 +00001657 if (II->isStr("show")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001658 Action = Sema::PSK_Show;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001659 PP.Lex(Tok);
1660 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001661 if (II->isStr("push")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001662 Action = Sema::PSK_Push;
Chris Lattnere3d20d92008-11-23 21:45:46 +00001663 } else if (II->isStr("pop")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001664 Action = Sema::PSK_Pop;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001665 } else {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001666 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001667 return;
Mike Stump11289f42009-09-09 15:08:12 +00001668 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001669 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001670
Daniel Dunbar921b9682008-10-04 19:21:03 +00001671 if (Tok.is(tok::comma)) {
1672 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001673
Daniel Dunbar921b9682008-10-04 19:21:03 +00001674 if (Tok.is(tok::numeric_constant)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001675 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001676 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001677
1678 PP.Lex(Tok);
1679 } else if (Tok.is(tok::identifier)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001680 SlotLabel = Tok.getIdentifierInfo()->getName();
Daniel Dunbar921b9682008-10-04 19:21:03 +00001681 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001682
Daniel Dunbar921b9682008-10-04 19:21:03 +00001683 if (Tok.is(tok::comma)) {
1684 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001685
Daniel Dunbar921b9682008-10-04 19:21:03 +00001686 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001687 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001688 return;
1689 }
Mike Stump11289f42009-09-09 15:08:12 +00001690
Denis Zobnin10c4f452016-04-29 18:17:40 +00001691 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001692 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001693
1694 PP.Lex(Tok);
1695 }
1696 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001697 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001698 return;
1699 }
1700 }
1701 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001702 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman055c9702011-11-02 01:53:16 +00001703 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
1704 // the push/pop stack.
1705 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
Denis Zobnin10c4f452016-04-29 18:17:40 +00001706 Action = Sema::PSK_Pop;
Sebastian Redl17f2c7d2008-12-09 13:15:23 +00001707 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001708
1709 if (Tok.isNot(tok::r_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001710 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001711 return;
1712 }
1713
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001714 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001715 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001716 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001717 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
1718 return;
1719 }
1720
David Blaikie2eabcc92016-02-09 18:52:09 +00001721 PragmaPackInfo *Info =
1722 PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
Denis Zobnin10c4f452016-04-29 18:17:40 +00001723 Info->Action = Action;
1724 Info->SlotLabel = SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001725 Info->Alignment = Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +00001726
David Blaikie2eabcc92016-02-09 18:52:09 +00001727 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1728 1);
Eli Friedmanec52f922012-02-23 23:47:16 +00001729 Toks[0].startToken();
1730 Toks[0].setKind(tok::annot_pragma_pack);
1731 Toks[0].setLocation(PackLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001732 Toks[0].setAnnotationEndLoc(RParenLoc);
Eli Friedmanec52f922012-02-23 23:47:16 +00001733 Toks[0].setAnnotationValue(static_cast<void*>(Info));
David Blaikie2eabcc92016-02-09 18:52:09 +00001734 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001735}
1736
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001737// #pragma ms_struct on
1738// #pragma ms_struct off
Fangrui Song6907ce22018-07-30 19:24:48 +00001739void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001740 PragmaIntroducerKind Introducer,
1741 Token &MSStructTok) {
Nico Weber779355f2016-03-02 23:22:00 +00001742 PragmaMSStructKind Kind = PMSST_OFF;
1743
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001744 Token Tok;
1745 PP.Lex(Tok);
1746 if (Tok.isNot(tok::identifier)) {
1747 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1748 return;
1749 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001750 SourceLocation EndLoc = Tok.getLocation();
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001751 const IdentifierInfo *II = Tok.getIdentifierInfo();
1752 if (II->isStr("on")) {
Nico Weber779355f2016-03-02 23:22:00 +00001753 Kind = PMSST_ON;
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001754 PP.Lex(Tok);
1755 }
1756 else if (II->isStr("off") || II->isStr("reset"))
1757 PP.Lex(Tok);
1758 else {
1759 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1760 return;
1761 }
Fangrui Song6907ce22018-07-30 19:24:48 +00001762
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001763 if (Tok.isNot(tok::eod)) {
Daniel Dunbar340cf242012-02-29 01:38:22 +00001764 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1765 << "ms_struct";
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001766 return;
1767 }
Eli Friedman68be1642012-10-04 02:36:51 +00001768
David Blaikie2eabcc92016-02-09 18:52:09 +00001769 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1770 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001771 Toks[0].startToken();
1772 Toks[0].setKind(tok::annot_pragma_msstruct);
1773 Toks[0].setLocation(MSStructTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001774 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001775 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1776 static_cast<uintptr_t>(Kind)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001777 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001778}
1779
Javed Absar2a67c9e2017-06-05 10:11:57 +00001780// #pragma clang section bss="abc" data="" rodata="def" text=""
1781void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
1782 PragmaIntroducerKind Introducer, Token &FirstToken) {
1783
1784 Token Tok;
1785 auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;
1786
1787 PP.Lex(Tok); // eat 'section'
1788 while (Tok.isNot(tok::eod)) {
1789 if (Tok.isNot(tok::identifier)) {
1790 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1791 return;
1792 }
1793
1794 const IdentifierInfo *SecType = Tok.getIdentifierInfo();
1795 if (SecType->isStr("bss"))
1796 SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;
1797 else if (SecType->isStr("data"))
1798 SecKind = Sema::PragmaClangSectionKind::PCSK_Data;
1799 else if (SecType->isStr("rodata"))
1800 SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;
1801 else if (SecType->isStr("text"))
1802 SecKind = Sema::PragmaClangSectionKind::PCSK_Text;
1803 else {
1804 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1805 return;
1806 }
1807
1808 PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
1809 if (Tok.isNot(tok::equal)) {
1810 PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
1811 return;
1812 }
1813
1814 std::string SecName;
1815 if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
1816 return;
1817
1818 Actions.ActOnPragmaClangSection(Tok.getLocation(),
1819 (SecName.size()? Sema::PragmaClangSectionAction::PCSA_Set :
1820 Sema::PragmaClangSectionAction::PCSA_Clear),
1821 SecKind, SecName);
1822 }
1823}
1824
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001825// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
1826// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman68be1642012-10-04 02:36:51 +00001827static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001828 bool IsOptions) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001829 Token Tok;
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001830
1831 if (IsOptions) {
1832 PP.Lex(Tok);
1833 if (Tok.isNot(tok::identifier) ||
1834 !Tok.getIdentifierInfo()->isStr("align")) {
1835 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
1836 return;
1837 }
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001838 }
Daniel Dunbar663e8092010-05-27 18:42:09 +00001839
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001840 PP.Lex(Tok);
1841 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001842 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
1843 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001844 return;
1845 }
1846
1847 PP.Lex(Tok);
1848 if (Tok.isNot(tok::identifier)) {
1849 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001850 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001851 return;
1852 }
1853
John McCallfaf5fb42010-08-26 23:41:50 +00001854 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001855 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar663e8092010-05-27 18:42:09 +00001856 if (II->isStr("native"))
John McCallfaf5fb42010-08-26 23:41:50 +00001857 Kind = Sema::POAK_Native;
Daniel Dunbar663e8092010-05-27 18:42:09 +00001858 else if (II->isStr("natural"))
John McCallfaf5fb42010-08-26 23:41:50 +00001859 Kind = Sema::POAK_Natural;
Daniel Dunbar9c84d4a2010-05-27 18:42:17 +00001860 else if (II->isStr("packed"))
John McCallfaf5fb42010-08-26 23:41:50 +00001861 Kind = Sema::POAK_Packed;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001862 else if (II->isStr("power"))
John McCallfaf5fb42010-08-26 23:41:50 +00001863 Kind = Sema::POAK_Power;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001864 else if (II->isStr("mac68k"))
John McCallfaf5fb42010-08-26 23:41:50 +00001865 Kind = Sema::POAK_Mac68k;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001866 else if (II->isStr("reset"))
John McCallfaf5fb42010-08-26 23:41:50 +00001867 Kind = Sema::POAK_Reset;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001868 else {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001869 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
1870 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001871 return;
1872 }
1873
David Majnemera8f2f1d2015-03-19 00:10:23 +00001874 SourceLocation EndLoc = Tok.getLocation();
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001875 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001876 if (Tok.isNot(tok::eod)) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001877 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001878 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001879 return;
1880 }
1881
David Blaikie2eabcc92016-02-09 18:52:09 +00001882 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1883 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001884 Toks[0].startToken();
1885 Toks[0].setKind(tok::annot_pragma_align);
1886 Toks[0].setLocation(FirstTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001887 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001888 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1889 static_cast<uintptr_t>(Kind)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001890 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001891}
1892
Fangrui Song6907ce22018-07-30 19:24:48 +00001893void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
Douglas Gregorc7d65762010-09-09 22:45:38 +00001894 PragmaIntroducerKind Introducer,
1895 Token &AlignTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001896 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001897}
1898
Fangrui Song6907ce22018-07-30 19:24:48 +00001899void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
Douglas Gregorc7d65762010-09-09 22:45:38 +00001900 PragmaIntroducerKind Introducer,
1901 Token &OptionsTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001902 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001903}
1904
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001905// #pragma unused(identifier)
Fangrui Song6907ce22018-07-30 19:24:48 +00001906void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
Douglas Gregorc7d65762010-09-09 22:45:38 +00001907 PragmaIntroducerKind Introducer,
1908 Token &UnusedTok) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001909 // FIXME: Should we be expanding macros here? My guess is no.
1910 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +00001911
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001912 // Lex the left '('.
1913 Token Tok;
1914 PP.Lex(Tok);
1915 if (Tok.isNot(tok::l_paren)) {
1916 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
1917 return;
1918 }
Mike Stump11289f42009-09-09 15:08:12 +00001919
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001920 // Lex the declaration reference(s).
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001921 SmallVector<Token, 5> Identifiers;
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001922 SourceLocation RParenLoc;
1923 bool LexID = true;
Mike Stump11289f42009-09-09 15:08:12 +00001924
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001925 while (true) {
1926 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001927
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001928 if (LexID) {
Mike Stump11289f42009-09-09 15:08:12 +00001929 if (Tok.is(tok::identifier)) {
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001930 Identifiers.push_back(Tok);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001931 LexID = false;
1932 continue;
1933 }
1934
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001935 // Illegal token!
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001936 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
1937 return;
1938 }
Mike Stump11289f42009-09-09 15:08:12 +00001939
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001940 // We are execting a ')' or a ','.
1941 if (Tok.is(tok::comma)) {
1942 LexID = true;
1943 continue;
1944 }
Mike Stump11289f42009-09-09 15:08:12 +00001945
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001946 if (Tok.is(tok::r_paren)) {
1947 RParenLoc = Tok.getLocation();
1948 break;
1949 }
Mike Stump11289f42009-09-09 15:08:12 +00001950
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001951 // Illegal token!
David Majnemer88969812014-02-10 19:06:37 +00001952 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001953 return;
1954 }
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001955
1956 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001957 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001958 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1959 "unused";
1960 return;
1961 }
1962
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001963 // Verify that we have a location for the right parenthesis.
1964 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001965 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001966
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001967 // For each identifier token, insert into the token stream a
1968 // annot_pragma_unused token followed by the identifier token.
1969 // This allows us to cache a "#pragma unused" that occurs inside an inline
1970 // C++ member function.
1971
David Blaikie2eabcc92016-02-09 18:52:09 +00001972 MutableArrayRef<Token> Toks(
1973 PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
1974 2 * Identifiers.size());
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001975 for (unsigned i=0; i != Identifiers.size(); i++) {
1976 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
1977 pragmaUnusedTok.startToken();
1978 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
1979 pragmaUnusedTok.setLocation(UnusedLoc);
1980 idTok = Identifiers[i];
1981 }
David Blaikie2eabcc92016-02-09 18:52:09 +00001982 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001983}
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001984
1985// #pragma weak identifier
1986// #pragma weak identifier '=' identifier
Fangrui Song6907ce22018-07-30 19:24:48 +00001987void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
Douglas Gregorc7d65762010-09-09 22:45:38 +00001988 PragmaIntroducerKind Introducer,
1989 Token &WeakTok) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001990 SourceLocation WeakLoc = WeakTok.getLocation();
1991
1992 Token Tok;
1993 PP.Lex(Tok);
1994 if (Tok.isNot(tok::identifier)) {
1995 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
1996 return;
1997 }
1998
Eli Friedman68be1642012-10-04 02:36:51 +00001999 Token WeakName = Tok;
2000 bool HasAlias = false;
2001 Token AliasName;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002002
2003 PP.Lex(Tok);
2004 if (Tok.is(tok::equal)) {
Eli Friedman68be1642012-10-04 02:36:51 +00002005 HasAlias = true;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002006 PP.Lex(Tok);
2007 if (Tok.isNot(tok::identifier)) {
Mike Stump11289f42009-09-09 15:08:12 +00002008 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002009 << "weak";
2010 return;
2011 }
Eli Friedman68be1642012-10-04 02:36:51 +00002012 AliasName = Tok;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002013 PP.Lex(Tok);
2014 }
2015
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00002016 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002017 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
2018 return;
2019 }
2020
Eli Friedman68be1642012-10-04 02:36:51 +00002021 if (HasAlias) {
David Blaikie2eabcc92016-02-09 18:52:09 +00002022 MutableArrayRef<Token> Toks(
2023 PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
Eli Friedman68be1642012-10-04 02:36:51 +00002024 Token &pragmaUnusedTok = Toks[0];
2025 pragmaUnusedTok.startToken();
2026 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
2027 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002028 pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00002029 Toks[1] = WeakName;
2030 Toks[2] = AliasName;
David Blaikie2eabcc92016-02-09 18:52:09 +00002031 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002032 } else {
David Blaikie2eabcc92016-02-09 18:52:09 +00002033 MutableArrayRef<Token> Toks(
2034 PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
Eli Friedman68be1642012-10-04 02:36:51 +00002035 Token &pragmaUnusedTok = Toks[0];
2036 pragmaUnusedTok.startToken();
2037 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
2038 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002039 pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00002040 Toks[1] = WeakName;
David Blaikie2eabcc92016-02-09 18:52:09 +00002041 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002042 }
2043}
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00002044
David Chisnall0867d9c2012-02-18 16:12:34 +00002045// #pragma redefine_extname identifier identifier
Fangrui Song6907ce22018-07-30 19:24:48 +00002046void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
David Chisnall0867d9c2012-02-18 16:12:34 +00002047 PragmaIntroducerKind Introducer,
2048 Token &RedefToken) {
2049 SourceLocation RedefLoc = RedefToken.getLocation();
2050
2051 Token Tok;
2052 PP.Lex(Tok);
2053 if (Tok.isNot(tok::identifier)) {
2054 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2055 "redefine_extname";
2056 return;
2057 }
2058
Eli Friedman68be1642012-10-04 02:36:51 +00002059 Token RedefName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00002060 PP.Lex(Tok);
Eli Friedman68be1642012-10-04 02:36:51 +00002061
David Chisnall0867d9c2012-02-18 16:12:34 +00002062 if (Tok.isNot(tok::identifier)) {
2063 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2064 << "redefine_extname";
2065 return;
2066 }
Eli Friedman68be1642012-10-04 02:36:51 +00002067
2068 Token AliasName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00002069 PP.Lex(Tok);
2070
2071 if (Tok.isNot(tok::eod)) {
2072 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2073 "redefine_extname";
2074 return;
2075 }
2076
David Blaikie2eabcc92016-02-09 18:52:09 +00002077 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),
2078 3);
Eli Friedman68be1642012-10-04 02:36:51 +00002079 Token &pragmaRedefTok = Toks[0];
2080 pragmaRedefTok.startToken();
2081 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
2082 pragmaRedefTok.setLocation(RedefLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002083 pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00002084 Toks[1] = RedefName;
2085 Toks[2] = AliasName;
David Blaikie2eabcc92016-02-09 18:52:09 +00002086 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
David Chisnall0867d9c2012-02-18 16:12:34 +00002087}
2088
2089
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00002090void
Fangrui Song6907ce22018-07-30 19:24:48 +00002091PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00002092 PragmaIntroducerKind Introducer,
2093 Token &Tok) {
2094 tok::OnOffSwitch OOS;
2095 if (PP.LexOnOffSwitch(OOS))
2096 return;
2097
David Blaikie2eabcc92016-02-09 18:52:09 +00002098 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2099 1);
Eli Friedman68be1642012-10-04 02:36:51 +00002100 Toks[0].startToken();
2101 Toks[0].setKind(tok::annot_pragma_fp_contract);
2102 Toks[0].setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002103 Toks[0].setAnnotationEndLoc(Tok.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00002104 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2105 static_cast<uintptr_t>(OOS)));
David Blaikie2eabcc92016-02-09 18:52:09 +00002106 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00002107}
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002108
Fangrui Song6907ce22018-07-30 19:24:48 +00002109void
2110PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002111 PragmaIntroducerKind Introducer,
2112 Token &Tok) {
Tanya Lattneree840b82011-04-14 23:35:31 +00002113 PP.LexUnexpandedToken(Tok);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002114 if (Tok.isNot(tok::identifier)) {
2115 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2116 "OPENCL";
2117 return;
2118 }
Yaxun Liu5b746652016-12-18 05:18:55 +00002119 IdentifierInfo *Ext = Tok.getIdentifierInfo();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002120 SourceLocation NameLoc = Tok.getLocation();
2121
2122 PP.Lex(Tok);
2123 if (Tok.isNot(tok::colon)) {
Yaxun Liu5b746652016-12-18 05:18:55 +00002124 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002125 return;
2126 }
2127
2128 PP.Lex(Tok);
2129 if (Tok.isNot(tok::identifier)) {
Yaxun Liu5b746652016-12-18 05:18:55 +00002130 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002131 return;
2132 }
Yaxun Liu5b746652016-12-18 05:18:55 +00002133 IdentifierInfo *Pred = Tok.getIdentifierInfo();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002134
Yaxun Liu5b746652016-12-18 05:18:55 +00002135 OpenCLExtState State;
2136 if (Pred->isStr("enable")) {
2137 State = Enable;
2138 } else if (Pred->isStr("disable")) {
2139 State = Disable;
2140 } else if (Pred->isStr("begin"))
2141 State = Begin;
2142 else if (Pred->isStr("end"))
2143 State = End;
2144 else {
2145 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
2146 << Ext->isStr("all");
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002147 return;
2148 }
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00002149 SourceLocation StateLoc = Tok.getLocation();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002150
Eli Friedman68be1642012-10-04 02:36:51 +00002151 PP.Lex(Tok);
2152 if (Tok.isNot(tok::eod)) {
2153 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2154 "OPENCL EXTENSION";
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002155 return;
2156 }
Eli Friedman68be1642012-10-04 02:36:51 +00002157
Yaxun Liu5b746652016-12-18 05:18:55 +00002158 auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
2159 Info->first = Ext;
2160 Info->second = State;
David Blaikie2eabcc92016-02-09 18:52:09 +00002161 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2162 1);
Eli Friedman68be1642012-10-04 02:36:51 +00002163 Toks[0].startToken();
2164 Toks[0].setKind(tok::annot_pragma_opencl_extension);
2165 Toks[0].setLocation(NameLoc);
Yaxun Liu5b746652016-12-18 05:18:55 +00002166 Toks[0].setAnnotationValue(static_cast<void*>(Info));
David Majnemera8f2f1d2015-03-19 00:10:23 +00002167 Toks[0].setAnnotationEndLoc(StateLoc);
David Blaikie2eabcc92016-02-09 18:52:09 +00002168 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00002169
2170 if (PP.getPPCallbacks())
Fangrui Song6907ce22018-07-30 19:24:48 +00002171 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
Yaxun Liu5b746652016-12-18 05:18:55 +00002172 StateLoc, State);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002173}
2174
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002175/// Handle '#pragma omp ...' when OpenMP is disabled.
Alexey Bataeva769e072013-03-22 06:34:35 +00002176///
2177void
2178PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
2179 PragmaIntroducerKind Introducer,
2180 Token &FirstTok) {
Alp Tokerd4a3f0e2014-06-15 23:30:39 +00002181 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
2182 FirstTok.getLocation())) {
Alexey Bataeva769e072013-03-22 06:34:35 +00002183 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
Alp Tokerd576e002014-06-12 11:13:52 +00002184 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
2185 diag::Severity::Ignored, SourceLocation());
Alexey Bataeva769e072013-03-22 06:34:35 +00002186 }
2187 PP.DiscardUntilEndOfDirective();
2188}
2189
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002190/// Handle '#pragma omp ...' when OpenMP is enabled.
Alexey Bataeva769e072013-03-22 06:34:35 +00002191///
2192void
2193PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
2194 PragmaIntroducerKind Introducer,
2195 Token &FirstTok) {
2196 SmallVector<Token, 16> Pragma;
2197 Token Tok;
2198 Tok.startToken();
2199 Tok.setKind(tok::annot_pragma_openmp);
2200 Tok.setLocation(FirstTok.getLocation());
2201
Alexey Bataev96dae812018-02-16 18:36:44 +00002202 while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) {
Alexey Bataeva769e072013-03-22 06:34:35 +00002203 Pragma.push_back(Tok);
2204 PP.Lex(Tok);
Alexey Bataev96dae812018-02-16 18:36:44 +00002205 if (Tok.is(tok::annot_pragma_openmp)) {
2206 PP.Diag(Tok, diag::err_omp_unexpected_directive) << 0;
2207 unsigned InnerPragmaCnt = 1;
2208 while (InnerPragmaCnt != 0) {
2209 PP.Lex(Tok);
2210 if (Tok.is(tok::annot_pragma_openmp))
2211 ++InnerPragmaCnt;
2212 else if (Tok.is(tok::annot_pragma_openmp_end))
2213 --InnerPragmaCnt;
2214 }
2215 PP.Lex(Tok);
2216 }
Alexey Bataeva769e072013-03-22 06:34:35 +00002217 }
2218 SourceLocation EodLoc = Tok.getLocation();
2219 Tok.startToken();
2220 Tok.setKind(tok::annot_pragma_openmp_end);
2221 Tok.setLocation(EodLoc);
2222 Pragma.push_back(Tok);
2223
David Blaikie2eabcc92016-02-09 18:52:09 +00002224 auto Toks = llvm::make_unique<Token[]>(Pragma.size());
2225 std::copy(Pragma.begin(), Pragma.end(), Toks.get());
2226 PP.EnterTokenStream(std::move(Toks), Pragma.size(),
2227 /*DisableMacroExpansion=*/false);
Alexey Bataeva769e072013-03-22 06:34:35 +00002228}
Reid Kleckner002562a2013-05-06 21:02:12 +00002229
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002230/// Handle '#pragma pointers_to_members'
David Majnemer4bb09802014-02-10 19:50:15 +00002231// The grammar for this pragma is as follows:
2232//
2233// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
2234//
2235// #pragma pointers_to_members '(' 'best_case' ')'
2236// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
2237// #pragma pointers_to_members '(' inheritance-model ')'
2238void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
2239 PragmaIntroducerKind Introducer,
2240 Token &Tok) {
2241 SourceLocation PointersToMembersLoc = Tok.getLocation();
2242 PP.Lex(Tok);
2243 if (Tok.isNot(tok::l_paren)) {
2244 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
2245 << "pointers_to_members";
2246 return;
2247 }
2248 PP.Lex(Tok);
2249 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
2250 if (!Arg) {
2251 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2252 << "pointers_to_members";
2253 return;
2254 }
2255 PP.Lex(Tok);
2256
David Majnemer86c318f2014-02-11 21:05:00 +00002257 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
David Majnemer4bb09802014-02-10 19:50:15 +00002258 if (Arg->isStr("best_case")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002259 RepresentationMethod = LangOptions::PPTMK_BestCase;
David Majnemer4bb09802014-02-10 19:50:15 +00002260 } else {
2261 if (Arg->isStr("full_generality")) {
2262 if (Tok.is(tok::comma)) {
2263 PP.Lex(Tok);
2264
2265 Arg = Tok.getIdentifierInfo();
2266 if (!Arg) {
2267 PP.Diag(Tok.getLocation(),
2268 diag::err_pragma_pointers_to_members_unknown_kind)
2269 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
2270 return;
2271 }
2272 PP.Lex(Tok);
2273 } else if (Tok.is(tok::r_paren)) {
2274 // #pragma pointers_to_members(full_generality) implicitly specifies
2275 // virtual_inheritance.
Craig Topper161e4db2014-05-21 06:02:52 +00002276 Arg = nullptr;
David Majnemer86c318f2014-02-11 21:05:00 +00002277 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002278 } else {
2279 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
2280 << "full_generality";
2281 return;
2282 }
2283 }
2284
2285 if (Arg) {
2286 if (Arg->isStr("single_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002287 RepresentationMethod =
2288 LangOptions::PPTMK_FullGeneralitySingleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002289 } else if (Arg->isStr("multiple_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002290 RepresentationMethod =
2291 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002292 } else if (Arg->isStr("virtual_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002293 RepresentationMethod =
2294 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002295 } else {
2296 PP.Diag(Tok.getLocation(),
2297 diag::err_pragma_pointers_to_members_unknown_kind)
2298 << Arg << /*HasPointerDeclaration*/ 1;
2299 return;
2300 }
2301 }
2302 }
2303
2304 if (Tok.isNot(tok::r_paren)) {
2305 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
2306 << (Arg ? Arg->getName() : "full_generality");
2307 return;
2308 }
2309
David Majnemera8f2f1d2015-03-19 00:10:23 +00002310 SourceLocation EndLoc = Tok.getLocation();
David Majnemer4bb09802014-02-10 19:50:15 +00002311 PP.Lex(Tok);
2312 if (Tok.isNot(tok::eod)) {
2313 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2314 << "pointers_to_members";
2315 return;
2316 }
2317
2318 Token AnnotTok;
2319 AnnotTok.startToken();
2320 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
2321 AnnotTok.setLocation(PointersToMembersLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002322 AnnotTok.setAnnotationEndLoc(EndLoc);
David Majnemer4bb09802014-02-10 19:50:15 +00002323 AnnotTok.setAnnotationValue(
2324 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
2325 PP.EnterToken(AnnotTok);
2326}
2327
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002328/// Handle '#pragma vtordisp'
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002329// The grammar for this pragma is as follows:
2330//
2331// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
2332//
2333// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
2334// #pragma vtordisp '(' 'pop' ')'
2335// #pragma vtordisp '(' ')'
2336void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
2337 PragmaIntroducerKind Introducer,
2338 Token &Tok) {
2339 SourceLocation VtorDispLoc = Tok.getLocation();
2340 PP.Lex(Tok);
2341 if (Tok.isNot(tok::l_paren)) {
2342 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
2343 return;
2344 }
2345 PP.Lex(Tok);
2346
Denis Zobnin2290dac2016-04-29 11:27:00 +00002347 Sema::PragmaMsStackAction Action = Sema::PSK_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002348 const IdentifierInfo *II = Tok.getIdentifierInfo();
2349 if (II) {
2350 if (II->isStr("push")) {
2351 // #pragma vtordisp(push, mode)
2352 PP.Lex(Tok);
2353 if (Tok.isNot(tok::comma)) {
2354 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
2355 return;
2356 }
2357 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00002358 Action = Sema::PSK_Push_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002359 // not push, could be on/off
2360 } else if (II->isStr("pop")) {
2361 // #pragma vtordisp(pop)
2362 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00002363 Action = Sema::PSK_Pop;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002364 }
2365 // not push or pop, could be on/off
2366 } else {
2367 if (Tok.is(tok::r_paren)) {
2368 // #pragma vtordisp()
Denis Zobnin2290dac2016-04-29 11:27:00 +00002369 Action = Sema::PSK_Reset;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002370 }
2371 }
2372
2373
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00002374 uint64_t Value = 0;
Denis Zobnin2290dac2016-04-29 11:27:00 +00002375 if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002376 const IdentifierInfo *II = Tok.getIdentifierInfo();
2377 if (II && II->isStr("off")) {
2378 PP.Lex(Tok);
2379 Value = 0;
2380 } else if (II && II->isStr("on")) {
2381 PP.Lex(Tok);
2382 Value = 1;
2383 } else if (Tok.is(tok::numeric_constant) &&
2384 PP.parseSimpleIntegerLiteral(Tok, Value)) {
2385 if (Value > 2) {
2386 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
2387 << 0 << 2 << "vtordisp";
2388 return;
2389 }
2390 } else {
2391 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
2392 << "vtordisp";
2393 return;
2394 }
2395 }
2396
2397 // Finish the pragma: ')' $
2398 if (Tok.isNot(tok::r_paren)) {
2399 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
2400 return;
2401 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00002402 SourceLocation EndLoc = Tok.getLocation();
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002403 PP.Lex(Tok);
2404 if (Tok.isNot(tok::eod)) {
2405 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2406 << "vtordisp";
2407 return;
2408 }
2409
2410 // Enter the annotation.
2411 Token AnnotTok;
2412 AnnotTok.startToken();
2413 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
2414 AnnotTok.setLocation(VtorDispLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002415 AnnotTok.setAnnotationEndLoc(EndLoc);
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00002416 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
Denis Zobnin2290dac2016-04-29 11:27:00 +00002417 static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002418 PP.EnterToken(AnnotTok);
2419}
2420
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002421/// Handle all MS pragmas. Simply forwards the tokens after inserting
Warren Huntc3b18962014-04-08 22:30:47 +00002422/// an annotation token.
2423void PragmaMSPragma::HandlePragma(Preprocessor &PP,
2424 PragmaIntroducerKind Introducer,
2425 Token &Tok) {
2426 Token EoF, AnnotTok;
2427 EoF.startToken();
2428 EoF.setKind(tok::eof);
2429 AnnotTok.startToken();
2430 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
2431 AnnotTok.setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002432 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
Warren Huntc3b18962014-04-08 22:30:47 +00002433 SmallVector<Token, 8> TokenVector;
2434 // Suck up all of the tokens before the eod.
David Majnemera8f2f1d2015-03-19 00:10:23 +00002435 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
Warren Huntc3b18962014-04-08 22:30:47 +00002436 TokenVector.push_back(Tok);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002437 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
2438 }
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002439 // Add a sentinel EoF token to the end of the list.
Warren Huntc3b18962014-04-08 22:30:47 +00002440 TokenVector.push_back(EoF);
2441 // We must allocate this array with new because EnterTokenStream is going to
2442 // delete it later.
David Blaikie2eabcc92016-02-09 18:52:09 +00002443 auto TokenArray = llvm::make_unique<Token[]>(TokenVector.size());
2444 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
Warren Huntc3b18962014-04-08 22:30:47 +00002445 auto Value = new (PP.getPreprocessorAllocator())
David Blaikie2eabcc92016-02-09 18:52:09 +00002446 std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
2447 TokenVector.size());
Warren Huntc3b18962014-04-08 22:30:47 +00002448 AnnotTok.setAnnotationValue(Value);
2449 PP.EnterToken(AnnotTok);
Reid Klecknerd3923aa2014-04-03 19:04:24 +00002450}
2451
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002452/// Handle the Microsoft \#pragma detect_mismatch extension.
Aaron Ballman5d041be2013-06-04 02:07:14 +00002453///
2454/// The syntax is:
2455/// \code
2456/// #pragma detect_mismatch("name", "value")
2457/// \endcode
2458/// Where 'name' and 'value' are quoted strings. The values are embedded in
2459/// the object file and passed along to the linker. If the linker detects a
2460/// mismatch in the object file's values for the given name, a LNK2038 error
2461/// is emitted. See MSDN for more details.
2462void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
2463 PragmaIntroducerKind Introducer,
2464 Token &Tok) {
Nico Webercbbaeb12016-03-02 19:28:54 +00002465 SourceLocation DetectMismatchLoc = Tok.getLocation();
Aaron Ballman5d041be2013-06-04 02:07:14 +00002466 PP.Lex(Tok);
2467 if (Tok.isNot(tok::l_paren)) {
Nico Webercbbaeb12016-03-02 19:28:54 +00002468 PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00002469 return;
2470 }
2471
2472 // Read the name to embed, which must be a string literal.
2473 std::string NameString;
2474 if (!PP.LexStringLiteral(Tok, NameString,
2475 "pragma detect_mismatch",
2476 /*MacroExpansion=*/true))
2477 return;
2478
2479 // Read the comma followed by a second string literal.
2480 std::string ValueString;
2481 if (Tok.isNot(tok::comma)) {
2482 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2483 return;
2484 }
2485
2486 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
2487 /*MacroExpansion=*/true))
2488 return;
2489
2490 if (Tok.isNot(tok::r_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00002491 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00002492 return;
2493 }
2494 PP.Lex(Tok); // Eat the r_paren.
2495
2496 if (Tok.isNot(tok::eod)) {
2497 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2498 return;
2499 }
2500
Reid Kleckner71966c92014-02-20 23:37:45 +00002501 // If the pragma is lexically sound, notify any interested PPCallbacks.
2502 if (PP.getPPCallbacks())
Nico Webercbbaeb12016-03-02 19:28:54 +00002503 PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
Reid Kleckner71966c92014-02-20 23:37:45 +00002504 ValueString);
2505
Nico Webercbbaeb12016-03-02 19:28:54 +00002506 Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
Aaron Ballman5d041be2013-06-04 02:07:14 +00002507}
2508
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002509/// Handle the microsoft \#pragma comment extension.
Reid Kleckner002562a2013-05-06 21:02:12 +00002510///
2511/// The syntax is:
2512/// \code
2513/// #pragma comment(linker, "foo")
2514/// \endcode
2515/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
2516/// "foo" is a string, which is fully macro expanded, and permits string
2517/// concatenation, embedded escape characters etc. See MSDN for more details.
2518void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
2519 PragmaIntroducerKind Introducer,
2520 Token &Tok) {
2521 SourceLocation CommentLoc = Tok.getLocation();
2522 PP.Lex(Tok);
2523 if (Tok.isNot(tok::l_paren)) {
2524 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2525 return;
2526 }
2527
2528 // Read the identifier.
2529 PP.Lex(Tok);
2530 if (Tok.isNot(tok::identifier)) {
2531 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2532 return;
2533 }
2534
2535 // Verify that this is one of the 5 whitelisted options.
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002536 IdentifierInfo *II = Tok.getIdentifierInfo();
Nico Weber66220292016-03-02 17:28:48 +00002537 PragmaMSCommentKind Kind =
2538 llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
2539 .Case("linker", PCK_Linker)
2540 .Case("lib", PCK_Lib)
2541 .Case("compiler", PCK_Compiler)
2542 .Case("exestr", PCK_ExeStr)
2543 .Case("user", PCK_User)
2544 .Default(PCK_Unknown);
2545 if (Kind == PCK_Unknown) {
Reid Kleckner002562a2013-05-06 21:02:12 +00002546 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
2547 return;
2548 }
2549
Saleem Abdulrasoolfd4db532018-02-07 01:46:46 +00002550 if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) {
2551 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
2552 << II->getName();
2553 return;
2554 }
2555
Yunzhong Gao99efc032015-03-23 20:41:42 +00002556 // On PS4, issue a warning about any pragma comments other than
2557 // #pragma comment lib.
Nico Weber66220292016-03-02 17:28:48 +00002558 if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) {
Yunzhong Gao99efc032015-03-23 20:41:42 +00002559 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
2560 << II->getName();
2561 return;
2562 }
2563
Reid Kleckner002562a2013-05-06 21:02:12 +00002564 // Read the optional string if present.
2565 PP.Lex(Tok);
2566 std::string ArgumentString;
2567 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
2568 "pragma comment",
2569 /*MacroExpansion=*/true))
2570 return;
2571
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002572 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner002562a2013-05-06 21:02:12 +00002573 // FIXME: If the kind is "compiler" warn if the string is present (it is
2574 // ignored).
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002575 // The MSDN docs say that "lib" and "linker" require a string and have a short
2576 // whitelist of linker options they support, but in practice MSVC doesn't
2577 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner002562a2013-05-06 21:02:12 +00002578
2579 if (Tok.isNot(tok::r_paren)) {
2580 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2581 return;
2582 }
2583 PP.Lex(Tok); // eat the r_paren.
2584
2585 if (Tok.isNot(tok::eod)) {
2586 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2587 return;
2588 }
2589
Reid Kleckner71966c92014-02-20 23:37:45 +00002590 // If the pragma is lexically sound, notify any interested PPCallbacks.
2591 if (PP.getPPCallbacks())
2592 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
2593
Nico Weber66220292016-03-02 17:28:48 +00002594 Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
Reid Kleckner002562a2013-05-06 21:02:12 +00002595}
Dario Domizioli13a0a382014-05-23 12:13:25 +00002596
2597// #pragma clang optimize off
2598// #pragma clang optimize on
Fangrui Song6907ce22018-07-30 19:24:48 +00002599void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
Dario Domizioli13a0a382014-05-23 12:13:25 +00002600 PragmaIntroducerKind Introducer,
2601 Token &FirstToken) {
2602 Token Tok;
2603 PP.Lex(Tok);
2604 if (Tok.is(tok::eod)) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002605 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
Mark Heffernan450c2382014-07-23 17:31:31 +00002606 << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
Dario Domizioli13a0a382014-05-23 12:13:25 +00002607 return;
2608 }
2609 if (Tok.isNot(tok::identifier)) {
2610 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2611 << PP.getSpelling(Tok);
2612 return;
2613 }
2614 const IdentifierInfo *II = Tok.getIdentifierInfo();
2615 // The only accepted values are 'on' or 'off'.
2616 bool IsOn = false;
2617 if (II->isStr("on")) {
2618 IsOn = true;
2619 } else if (!II->isStr("off")) {
2620 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2621 << PP.getSpelling(Tok);
2622 return;
2623 }
2624 PP.Lex(Tok);
Fangrui Song6907ce22018-07-30 19:24:48 +00002625
Dario Domizioli13a0a382014-05-23 12:13:25 +00002626 if (Tok.isNot(tok::eod)) {
2627 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
2628 << PP.getSpelling(Tok);
2629 return;
2630 }
Eli Bendersky06a40422014-06-06 20:31:48 +00002631
2632 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
2633}
2634
Adam Nemet60d32642017-04-04 21:18:36 +00002635namespace {
2636/// Used as the annotation value for tok::annot_pragma_fp.
2637struct TokFPAnnotValue {
2638 enum FlagKinds { Contract };
2639 enum FlagValues { On, Off, Fast };
2640
2641 FlagKinds FlagKind;
2642 FlagValues FlagValue;
2643};
2644} // end anonymous namespace
2645
2646void PragmaFPHandler::HandlePragma(Preprocessor &PP,
2647 PragmaIntroducerKind Introducer,
2648 Token &Tok) {
2649 // fp
2650 Token PragmaName = Tok;
2651 SmallVector<Token, 1> TokenList;
2652
2653 PP.Lex(Tok);
2654 if (Tok.isNot(tok::identifier)) {
2655 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2656 << /*MissingOption=*/true << "";
2657 return;
2658 }
2659
2660 while (Tok.is(tok::identifier)) {
2661 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2662
2663 auto FlagKind =
2664 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagKinds>>(
2665 OptionInfo->getName())
2666 .Case("contract", TokFPAnnotValue::Contract)
2667 .Default(None);
2668 if (!FlagKind) {
2669 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2670 << /*MissingOption=*/false << OptionInfo;
2671 return;
2672 }
2673 PP.Lex(Tok);
2674
2675 // Read '('
2676 if (Tok.isNot(tok::l_paren)) {
2677 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
2678 return;
2679 }
2680 PP.Lex(Tok);
2681
2682 if (Tok.isNot(tok::identifier)) {
2683 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
2684 << PP.getSpelling(Tok) << OptionInfo->getName();
2685 return;
2686 }
2687 const IdentifierInfo *II = Tok.getIdentifierInfo();
2688
2689 auto FlagValue =
2690 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagValues>>(
2691 II->getName())
2692 .Case("on", TokFPAnnotValue::On)
2693 .Case("off", TokFPAnnotValue::Off)
2694 .Case("fast", TokFPAnnotValue::Fast)
2695 .Default(llvm::None);
2696
2697 if (!FlagValue) {
2698 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
2699 << PP.getSpelling(Tok) << OptionInfo->getName();
2700 return;
2701 }
2702 PP.Lex(Tok);
2703
2704 // Read ')'
2705 if (Tok.isNot(tok::r_paren)) {
2706 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2707 return;
2708 }
2709 PP.Lex(Tok);
2710
2711 auto *AnnotValue = new (PP.getPreprocessorAllocator())
2712 TokFPAnnotValue{*FlagKind, *FlagValue};
2713 // Generate the loop hint token.
2714 Token FPTok;
2715 FPTok.startToken();
2716 FPTok.setKind(tok::annot_pragma_fp);
2717 FPTok.setLocation(PragmaName.getLocation());
2718 FPTok.setAnnotationEndLoc(PragmaName.getLocation());
2719 FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
2720 TokenList.push_back(FPTok);
2721 }
2722
2723 if (Tok.isNot(tok::eod)) {
2724 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2725 << "clang fp";
2726 return;
2727 }
2728
2729 auto TokenArray = llvm::make_unique<Token[]>(TokenList.size());
2730 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
2731
2732 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
2733 /*DisableMacroExpansion=*/false);
2734}
2735
2736void Parser::HandlePragmaFP() {
2737 assert(Tok.is(tok::annot_pragma_fp));
2738 auto *AnnotValue =
2739 reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
2740
2741 LangOptions::FPContractModeKind FPC;
2742 switch (AnnotValue->FlagValue) {
2743 case TokFPAnnotValue::On:
2744 FPC = LangOptions::FPC_On;
2745 break;
2746 case TokFPAnnotValue::Fast:
2747 FPC = LangOptions::FPC_Fast;
2748 break;
2749 case TokFPAnnotValue::Off:
2750 FPC = LangOptions::FPC_Off;
2751 break;
2752 }
2753
2754 Actions.ActOnPragmaFPContract(FPC);
Richard Smithaf3b3252017-05-18 19:21:48 +00002755 ConsumeAnnotationToken();
Adam Nemet60d32642017-04-04 21:18:36 +00002756}
2757
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002758/// Parses loop or unroll pragma hint value and fills in Info.
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002759static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
2760 Token Option, bool ValueInParens,
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002761 PragmaLoopHintInfo &Info) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002762 SmallVector<Token, 1> ValueList;
2763 int OpenParens = ValueInParens ? 1 : 0;
2764 // Read constant expression.
2765 while (Tok.isNot(tok::eod)) {
2766 if (Tok.is(tok::l_paren))
2767 OpenParens++;
2768 else if (Tok.is(tok::r_paren)) {
2769 OpenParens--;
2770 if (OpenParens == 0 && ValueInParens)
2771 break;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002772 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002773
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002774 ValueList.push_back(Tok);
2775 PP.Lex(Tok);
2776 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002777
2778 if (ValueInParens) {
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002779 // Read ')'
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002780 if (Tok.isNot(tok::r_paren)) {
2781 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2782 return true;
2783 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002784 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002785 }
2786
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002787 Token EOFTok;
2788 EOFTok.startToken();
2789 EOFTok.setKind(tok::eof);
2790 EOFTok.setLocation(Tok.getLocation());
2791 ValueList.push_back(EOFTok); // Terminates expression for parsing.
2792
Benjamin Kramerfa7f8552015-08-05 09:39:57 +00002793 Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002794
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002795 Info.PragmaName = PragmaName;
2796 Info.Option = Option;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002797 return false;
2798}
2799
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002800/// Handle the \#pragma clang loop directive.
Eli Bendersky06a40422014-06-06 20:31:48 +00002801/// #pragma clang 'loop' loop-hints
2802///
2803/// loop-hints:
2804/// loop-hint loop-hints[opt]
2805///
2806/// loop-hint:
2807/// 'vectorize' '(' loop-hint-keyword ')'
2808/// 'interleave' '(' loop-hint-keyword ')'
Mark Heffernan450c2382014-07-23 17:31:31 +00002809/// 'unroll' '(' unroll-hint-keyword ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00002810/// 'vectorize_width' '(' loop-hint-value ')'
2811/// 'interleave_count' '(' loop-hint-value ')'
Eli Bendersky86483b32014-06-11 17:56:26 +00002812/// 'unroll_count' '(' loop-hint-value ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00002813///
2814/// loop-hint-keyword:
2815/// 'enable'
2816/// 'disable'
Tyler Nowicki9d268e12015-06-11 23:23:17 +00002817/// 'assume_safety'
Eli Bendersky06a40422014-06-06 20:31:48 +00002818///
Mark Heffernan450c2382014-07-23 17:31:31 +00002819/// unroll-hint-keyword:
Mark Heffernan397a98d2015-08-10 17:29:39 +00002820/// 'enable'
Mark Heffernan450c2382014-07-23 17:31:31 +00002821/// 'disable'
Mark Heffernan397a98d2015-08-10 17:29:39 +00002822/// 'full'
Mark Heffernan450c2382014-07-23 17:31:31 +00002823///
Eli Bendersky06a40422014-06-06 20:31:48 +00002824/// loop-hint-value:
2825/// constant-expression
2826///
2827/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
2828/// try vectorizing the instructions of the loop it precedes. Specifying
2829/// interleave(enable) or interleave_count(_value_) instructs llvm to try
2830/// interleaving multiple iterations of the loop it precedes. The width of the
2831/// vector instructions is specified by vectorize_width() and the number of
2832/// interleaved loop iterations is specified by interleave_count(). Specifying a
2833/// value of 1 effectively disables vectorization/interleaving, even if it is
2834/// possible and profitable, and 0 is invalid. The loop vectorizer currently
2835/// only works on inner loops.
2836///
Eli Bendersky86483b32014-06-11 17:56:26 +00002837/// The unroll and unroll_count directives control the concatenation
Mark Heffernan397a98d2015-08-10 17:29:39 +00002838/// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
2839/// completely if the trip count is known at compile time and unroll partially
2840/// if the trip count is not known. Specifying unroll(full) is similar to
2841/// unroll(enable) but will unroll the loop only if the trip count is known at
2842/// compile time. Specifying unroll(disable) disables unrolling for the
2843/// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
2844/// loop the number of times indicated by the value.
Eli Bendersky06a40422014-06-06 20:31:48 +00002845void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
2846 PragmaIntroducerKind Introducer,
2847 Token &Tok) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002848 // Incoming token is "loop" from "#pragma clang loop".
2849 Token PragmaName = Tok;
Eli Bendersky06a40422014-06-06 20:31:48 +00002850 SmallVector<Token, 1> TokenList;
2851
2852 // Lex the optimization option and verify it is an identifier.
2853 PP.Lex(Tok);
2854 if (Tok.isNot(tok::identifier)) {
2855 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2856 << /*MissingOption=*/true << "";
2857 return;
2858 }
2859
2860 while (Tok.is(tok::identifier)) {
2861 Token Option = Tok;
2862 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2863
Eli Bendersky86483b32014-06-11 17:56:26 +00002864 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002865 .Case("vectorize", true)
2866 .Case("interleave", true)
2867 .Case("unroll", true)
Adam Nemet2de463e2016-06-14 12:04:26 +00002868 .Case("distribute", true)
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002869 .Case("vectorize_width", true)
2870 .Case("interleave_count", true)
2871 .Case("unroll_count", true)
2872 .Default(false);
Eli Bendersky86483b32014-06-11 17:56:26 +00002873 if (!OptionValid) {
Eli Bendersky06a40422014-06-06 20:31:48 +00002874 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2875 << /*MissingOption=*/false << OptionInfo;
2876 return;
2877 }
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002878 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002879
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002880 // Read '('
2881 if (Tok.isNot(tok::l_paren)) {
2882 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002883 return;
2884 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002885 PP.Lex(Tok);
2886
2887 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2888 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
2889 *Info))
2890 return;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002891
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002892 // Generate the loop hint token.
Eli Bendersky06a40422014-06-06 20:31:48 +00002893 Token LoopHintTok;
2894 LoopHintTok.startToken();
2895 LoopHintTok.setKind(tok::annot_pragma_loop_hint);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002896 LoopHintTok.setLocation(PragmaName.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002897 LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
Eli Bendersky06a40422014-06-06 20:31:48 +00002898 LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
2899 TokenList.push_back(LoopHintTok);
2900 }
2901
2902 if (Tok.isNot(tok::eod)) {
2903 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2904 << "clang loop";
2905 return;
2906 }
2907
David Blaikie2eabcc92016-02-09 18:52:09 +00002908 auto TokenArray = llvm::make_unique<Token[]>(TokenList.size());
2909 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
Eli Bendersky06a40422014-06-06 20:31:48 +00002910
David Blaikie2eabcc92016-02-09 18:52:09 +00002911 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
2912 /*DisableMacroExpansion=*/false);
Eli Bendersky06a40422014-06-06 20:31:48 +00002913}
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002914
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002915/// Handle the loop unroll optimization pragmas.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002916/// #pragma unroll
2917/// #pragma unroll unroll-hint-value
2918/// #pragma unroll '(' unroll-hint-value ')'
Mark Heffernanc888e412014-07-24 18:09:38 +00002919/// #pragma nounroll
David Greenc8e39242018-08-01 14:36:12 +00002920/// #pragma unroll_and_jam
2921/// #pragma unroll_and_jam unroll-hint-value
2922/// #pragma unroll_and_jam '(' unroll-hint-value ')'
2923/// #pragma nounroll_and_jam
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002924///
2925/// unroll-hint-value:
2926/// constant-expression
2927///
Mark Heffernanc888e412014-07-24 18:09:38 +00002928/// Loop unrolling hints can be specified with '#pragma unroll' or
2929/// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
2930/// contained in parentheses. With no argument the directive instructs llvm to
2931/// try to unroll the loop completely. A positive integer argument can be
2932/// specified to indicate the number of times the loop should be unrolled. To
2933/// maximize compatibility with other compilers the unroll count argument can be
2934/// specified with or without parentheses. Specifying, '#pragma nounroll'
2935/// disables unrolling of the loop.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002936void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
2937 PragmaIntroducerKind Introducer,
2938 Token &Tok) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002939 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
2940 // "#pragma nounroll".
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002941 Token PragmaName = Tok;
2942 PP.Lex(Tok);
2943 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2944 if (Tok.is(tok::eod)) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002945 // nounroll or unroll pragma without an argument.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002946 Info->PragmaName = PragmaName;
Aaron Ballmand6807da2014-08-01 12:41:37 +00002947 Info->Option.startToken();
David Greenc8e39242018-08-01 14:36:12 +00002948 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" ||
2949 PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam") {
Mark Heffernanc888e412014-07-24 18:09:38 +00002950 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
David Greenc8e39242018-08-01 14:36:12 +00002951 << PragmaName.getIdentifierInfo()->getName();
Mark Heffernanc888e412014-07-24 18:09:38 +00002952 return;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002953 } else {
2954 // Unroll pragma with an argument: "#pragma unroll N" or
2955 // "#pragma unroll(N)".
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002956 // Read '(' if it exists.
2957 bool ValueInParens = Tok.is(tok::l_paren);
2958 if (ValueInParens)
2959 PP.Lex(Tok);
2960
Aaron Ballmand0b090d2014-08-01 12:20:20 +00002961 Token Option;
2962 Option.startToken();
2963 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002964 return;
2965
2966 // In CUDA, the argument to '#pragma unroll' should not be contained in
2967 // parentheses.
2968 if (PP.getLangOpts().CUDA && ValueInParens)
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002969 PP.Diag(Info->Toks[0].getLocation(),
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002970 diag::warn_pragma_unroll_cuda_value_in_parens);
2971
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002972 if (Tok.isNot(tok::eod)) {
2973 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2974 << "unroll";
2975 return;
2976 }
2977 }
2978
2979 // Generate the hint token.
David Blaikie2eabcc92016-02-09 18:52:09 +00002980 auto TokenArray = llvm::make_unique<Token[]>(1);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002981 TokenArray[0].startToken();
2982 TokenArray[0].setKind(tok::annot_pragma_loop_hint);
2983 TokenArray[0].setLocation(PragmaName.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002984 TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002985 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
David Blaikie2eabcc92016-02-09 18:52:09 +00002986 PP.EnterTokenStream(std::move(TokenArray), 1,
2987 /*DisableMacroExpansion=*/false);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002988}
Reid Kleckner3f1ec622016-09-07 16:38:32 +00002989
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002990/// Handle the Microsoft \#pragma intrinsic extension.
Reid Kleckner3f1ec622016-09-07 16:38:32 +00002991///
2992/// The syntax is:
2993/// \code
2994/// #pragma intrinsic(memset)
2995/// #pragma intrinsic(strlen, memcpy)
2996/// \endcode
2997///
2998/// Pragma intrisic tells the compiler to use a builtin version of the
2999/// function. Clang does it anyway, so the pragma doesn't really do anything.
3000/// Anyway, we emit a warning if the function specified in \#pragma intrinsic
3001/// isn't an intrinsic in clang and suggest to include intrin.h.
3002void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
3003 PragmaIntroducerKind Introducer,
3004 Token &Tok) {
3005 PP.Lex(Tok);
3006
3007 if (Tok.isNot(tok::l_paren)) {
3008 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
3009 << "intrinsic";
3010 return;
3011 }
3012 PP.Lex(Tok);
3013
3014 bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
3015
3016 while (Tok.is(tok::identifier)) {
3017 IdentifierInfo *II = Tok.getIdentifierInfo();
3018 if (!II->getBuiltinID())
3019 PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
3020 << II << SuggestIntrinH;
3021
3022 PP.Lex(Tok);
3023 if (Tok.isNot(tok::comma))
3024 break;
3025 PP.Lex(Tok);
3026 }
3027
3028 if (Tok.isNot(tok::r_paren)) {
3029 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
3030 << "intrinsic";
3031 return;
3032 }
3033 PP.Lex(Tok);
3034
3035 if (Tok.isNot(tok::eod))
3036 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3037 << "intrinsic";
3038}
Hans Wennborg1bbe00e2018-03-20 08:53:11 +00003039
3040// #pragma optimize("gsty", on|off)
3041void PragmaMSOptimizeHandler::HandlePragma(Preprocessor &PP,
3042 PragmaIntroducerKind Introducer,
3043 Token &Tok) {
3044 SourceLocation StartLoc = Tok.getLocation();
3045 PP.Lex(Tok);
3046
3047 if (Tok.isNot(tok::l_paren)) {
3048 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "optimize";
3049 return;
3050 }
3051 PP.Lex(Tok);
3052
3053 if (Tok.isNot(tok::string_literal)) {
3054 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_string) << "optimize";
3055 return;
3056 }
3057 // We could syntax check the string but it's probably not worth the effort.
3058 PP.Lex(Tok);
3059
3060 if (Tok.isNot(tok::comma)) {
3061 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_comma) << "optimize";
3062 return;
3063 }
3064 PP.Lex(Tok);
3065
3066 if (Tok.is(tok::eod) || Tok.is(tok::r_paren)) {
3067 PP.Diag(Tok.getLocation(), diag::warn_pragma_missing_argument)
3068 << "optimize" << /*Expected=*/true << "'on' or 'off'";
3069 return;
3070 }
3071 IdentifierInfo *II = Tok.getIdentifierInfo();
3072 if (!II || (!II->isStr("on") && !II->isStr("off"))) {
3073 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
3074 << PP.getSpelling(Tok) << "optimize" << /*Expected=*/true
3075 << "'on' or 'off'";
3076 return;
3077 }
3078 PP.Lex(Tok);
3079
3080 if (Tok.isNot(tok::r_paren)) {
3081 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "optimize";
3082 return;
3083 }
3084 PP.Lex(Tok);
3085
3086 if (Tok.isNot(tok::eod)) {
3087 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3088 << "optimize";
3089 return;
3090 }
3091 PP.Diag(StartLoc, diag::warn_pragma_optimize);
3092}
3093
Justin Lebar67a78a62016-10-08 22:15:58 +00003094void PragmaForceCUDAHostDeviceHandler::HandlePragma(
3095 Preprocessor &PP, PragmaIntroducerKind Introducer, Token &Tok) {
3096 Token FirstTok = Tok;
3097
3098 PP.Lex(Tok);
3099 IdentifierInfo *Info = Tok.getIdentifierInfo();
3100 if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {
3101 PP.Diag(FirstTok.getLocation(),
3102 diag::warn_pragma_force_cuda_host_device_bad_arg);
3103 return;
3104 }
3105
3106 if (Info->isStr("begin"))
3107 Actions.PushForceCUDAHostDevice();
3108 else if (!Actions.PopForceCUDAHostDevice())
3109 PP.Diag(FirstTok.getLocation(),
3110 diag::err_pragma_cannot_end_force_cuda_host_device);
3111
3112 PP.Lex(Tok);
3113 if (!Tok.is(tok::eod))
3114 PP.Diag(FirstTok.getLocation(),
3115 diag::warn_pragma_force_cuda_host_device_bad_arg);
3116}
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003117
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003118/// Handle the #pragma clang attribute directive.
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003119///
3120/// The syntax is:
3121/// \code
Erik Pilkington0876cae2018-12-20 22:32:04 +00003122/// #pragma clang attribute push (attribute, subject-set)
Erik Pilkington7d180942018-10-29 17:38:42 +00003123/// #pragma clang attribute push
3124/// #pragma clang attribute (attribute, subject-set)
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003125/// #pragma clang attribute pop
3126/// \endcode
3127///
Erik Pilkington0876cae2018-12-20 22:32:04 +00003128/// There are also 'namespace' variants of push and pop directives. The bare
3129/// '#pragma clang attribute (attribute, subject-set)' version doesn't require a
3130/// namespace, since it always applies attributes to the most recently pushed
3131/// group, regardless of namespace.
3132/// \code
3133/// #pragma clang attribute namespace.push (attribute, subject-set)
3134/// #pragma clang attribute namespace.push
3135/// #pragma clang attribute namespace.pop
3136/// \endcode
3137///
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003138/// The subject-set clause defines the set of declarations which receive the
3139/// attribute. Its exact syntax is described in the LanguageExtensions document
3140/// in Clang's documentation.
3141///
3142/// This directive instructs the compiler to begin/finish applying the specified
3143/// attribute to the set of attribute-specific declarations in the active range
3144/// of the pragma.
3145void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
3146 PragmaIntroducerKind Introducer,
3147 Token &FirstToken) {
3148 Token Tok;
3149 PP.Lex(Tok);
3150 auto *Info = new (PP.getPreprocessorAllocator())
3151 PragmaAttributeInfo(AttributesForPragmaAttribute);
3152
Erik Pilkington0876cae2018-12-20 22:32:04 +00003153 // Parse the optional namespace followed by a period.
3154 if (Tok.is(tok::identifier)) {
3155 IdentifierInfo *II = Tok.getIdentifierInfo();
3156 if (!II->isStr("push") && !II->isStr("pop")) {
3157 Info->Namespace = II;
3158 PP.Lex(Tok);
3159
3160 if (!Tok.is(tok::period)) {
3161 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period)
3162 << II;
3163 return;
3164 }
3165 PP.Lex(Tok);
3166 }
3167 }
3168
Erik Pilkington7d180942018-10-29 17:38:42 +00003169 if (!Tok.isOneOf(tok::identifier, tok::l_paren)) {
3170 PP.Diag(Tok.getLocation(),
3171 diag::err_pragma_attribute_expected_push_pop_paren);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003172 return;
3173 }
Erik Pilkington7d180942018-10-29 17:38:42 +00003174
3175 // Determine what action this pragma clang attribute represents.
Erik Pilkington0876cae2018-12-20 22:32:04 +00003176 if (Tok.is(tok::l_paren)) {
3177 if (Info->Namespace) {
3178 PP.Diag(Tok.getLocation(),
3179 diag::err_pragma_attribute_namespace_on_attribute);
3180 PP.Diag(Tok.getLocation(),
3181 diag::note_pragma_attribute_namespace_on_attribute);
3182 return;
3183 }
Erik Pilkington7d180942018-10-29 17:38:42 +00003184 Info->Action = PragmaAttributeInfo::Attribute;
Erik Pilkington0876cae2018-12-20 22:32:04 +00003185 } else {
Erik Pilkington7d180942018-10-29 17:38:42 +00003186 const IdentifierInfo *II = Tok.getIdentifierInfo();
3187 if (II->isStr("push"))
3188 Info->Action = PragmaAttributeInfo::Push;
3189 else if (II->isStr("pop"))
3190 Info->Action = PragmaAttributeInfo::Pop;
3191 else {
3192 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
3193 << PP.getSpelling(Tok);
3194 return;
3195 }
3196
3197 PP.Lex(Tok);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003198 }
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003199
3200 // Parse the actual attribute.
Erik Pilkington7d180942018-10-29 17:38:42 +00003201 if ((Info->Action == PragmaAttributeInfo::Push && Tok.isNot(tok::eod)) ||
3202 Info->Action == PragmaAttributeInfo::Attribute) {
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003203 if (Tok.isNot(tok::l_paren)) {
3204 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3205 return;
3206 }
3207 PP.Lex(Tok);
3208
3209 // Lex the attribute tokens.
3210 SmallVector<Token, 16> AttributeTokens;
3211 int OpenParens = 1;
3212 while (Tok.isNot(tok::eod)) {
3213 if (Tok.is(tok::l_paren))
3214 OpenParens++;
3215 else if (Tok.is(tok::r_paren)) {
3216 OpenParens--;
3217 if (OpenParens == 0)
3218 break;
3219 }
3220
3221 AttributeTokens.push_back(Tok);
3222 PP.Lex(Tok);
3223 }
3224
3225 if (AttributeTokens.empty()) {
3226 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);
3227 return;
3228 }
3229 if (Tok.isNot(tok::r_paren)) {
3230 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3231 return;
3232 }
3233 SourceLocation EndLoc = Tok.getLocation();
3234 PP.Lex(Tok);
3235
3236 // Terminate the attribute for parsing.
3237 Token EOFTok;
3238 EOFTok.startToken();
3239 EOFTok.setKind(tok::eof);
3240 EOFTok.setLocation(EndLoc);
3241 AttributeTokens.push_back(EOFTok);
3242
3243 Info->Tokens =
3244 llvm::makeArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
3245 }
3246
3247 if (Tok.isNot(tok::eod))
3248 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3249 << "clang attribute";
3250
3251 // Generate the annotated pragma token.
3252 auto TokenArray = llvm::make_unique<Token[]>(1);
3253 TokenArray[0].startToken();
3254 TokenArray[0].setKind(tok::annot_pragma_attribute);
3255 TokenArray[0].setLocation(FirstToken.getLocation());
3256 TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation());
3257 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
3258 PP.EnterTokenStream(std::move(TokenArray), 1,
3259 /*DisableMacroExpansion=*/false);
3260}