1*67e74705SXin Li //===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
2*67e74705SXin Li //
3*67e74705SXin Li // The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li // This file implements the language specific #pragma handlers.
11*67e74705SXin Li //
12*67e74705SXin Li //===----------------------------------------------------------------------===//
13*67e74705SXin Li
14*67e74705SXin Li #include "RAIIObjectsForParser.h"
15*67e74705SXin Li #include "clang/AST/ASTContext.h"
16*67e74705SXin Li #include "clang/Basic/PragmaKinds.h"
17*67e74705SXin Li #include "clang/Basic/TargetInfo.h"
18*67e74705SXin Li #include "clang/Lex/Preprocessor.h"
19*67e74705SXin Li #include "clang/Parse/ParseDiagnostic.h"
20*67e74705SXin Li #include "clang/Parse/Parser.h"
21*67e74705SXin Li #include "clang/Sema/LoopHint.h"
22*67e74705SXin Li #include "clang/Sema/Scope.h"
23*67e74705SXin Li #include "llvm/ADT/StringSwitch.h"
24*67e74705SXin Li using namespace clang;
25*67e74705SXin Li
26*67e74705SXin Li namespace {
27*67e74705SXin Li
28*67e74705SXin Li struct PragmaAlignHandler : public PragmaHandler {
PragmaAlignHandler__anon55716a6f0111::PragmaAlignHandler29*67e74705SXin Li explicit PragmaAlignHandler() : PragmaHandler("align") {}
30*67e74705SXin Li void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
31*67e74705SXin Li Token &FirstToken) override;
32*67e74705SXin Li };
33*67e74705SXin Li
34*67e74705SXin Li struct PragmaGCCVisibilityHandler : public PragmaHandler {
PragmaGCCVisibilityHandler__anon55716a6f0111::PragmaGCCVisibilityHandler35*67e74705SXin Li explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
36*67e74705SXin Li void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
37*67e74705SXin Li Token &FirstToken) override;
38*67e74705SXin Li };
39*67e74705SXin Li
40*67e74705SXin Li struct PragmaOptionsHandler : public PragmaHandler {
PragmaOptionsHandler__anon55716a6f0111::PragmaOptionsHandler41*67e74705SXin Li explicit PragmaOptionsHandler() : PragmaHandler("options") {}
42*67e74705SXin Li void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
43*67e74705SXin Li Token &FirstToken) override;
44*67e74705SXin Li };
45*67e74705SXin Li
46*67e74705SXin Li struct PragmaPackHandler : public PragmaHandler {
PragmaPackHandler__anon55716a6f0111::PragmaPackHandler47*67e74705SXin Li explicit PragmaPackHandler() : PragmaHandler("pack") {}
48*67e74705SXin Li void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
49*67e74705SXin Li Token &FirstToken) override;
50*67e74705SXin Li };
51*67e74705SXin Li
52*67e74705SXin Li struct PragmaMSStructHandler : public PragmaHandler {
PragmaMSStructHandler__anon55716a6f0111::PragmaMSStructHandler53*67e74705SXin Li explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
54*67e74705SXin Li void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
55*67e74705SXin Li Token &FirstToken) override;
56*67e74705SXin Li };
57*67e74705SXin Li
58*67e74705SXin Li struct PragmaUnusedHandler : public PragmaHandler {
PragmaUnusedHandler__anon55716a6f0111::PragmaUnusedHandler59*67e74705SXin Li PragmaUnusedHandler() : PragmaHandler("unused") {}
60*67e74705SXin Li void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
61*67e74705SXin Li Token &FirstToken) override;
62*67e74705SXin Li };
63*67e74705SXin Li
64*67e74705SXin Li struct PragmaWeakHandler : public PragmaHandler {
PragmaWeakHandler__anon55716a6f0111::PragmaWeakHandler65*67e74705SXin Li explicit PragmaWeakHandler() : PragmaHandler("weak") {}
66*67e74705SXin Li void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
67*67e74705SXin Li Token &FirstToken) override;
68*67e74705SXin Li };
69*67e74705SXin Li
70*67e74705SXin Li struct PragmaRedefineExtnameHandler : public PragmaHandler {
PragmaRedefineExtnameHandler__anon55716a6f0111::PragmaRedefineExtnameHandler71*67e74705SXin Li explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
72*67e74705SXin Li void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
73*67e74705SXin Li Token &FirstToken) override;
74*67e74705SXin Li };
75*67e74705SXin Li
76*67e74705SXin Li struct PragmaOpenCLExtensionHandler : public PragmaHandler {
PragmaOpenCLExtensionHandler__anon55716a6f0111::PragmaOpenCLExtensionHandler77*67e74705SXin Li PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
78*67e74705SXin Li void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
79*67e74705SXin Li Token &FirstToken) override;
80*67e74705SXin Li };
81*67e74705SXin Li
82*67e74705SXin Li
83*67e74705SXin Li struct PragmaFPContractHandler : public PragmaHandler {
PragmaFPContractHandler__anon55716a6f0111::PragmaFPContractHandler84*67e74705SXin Li PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
85*67e74705SXin Li void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
86*67e74705SXin Li Token &FirstToken) override;
87*67e74705SXin Li };
88*67e74705SXin Li
89*67e74705SXin Li struct PragmaNoOpenMPHandler : public PragmaHandler {
PragmaNoOpenMPHandler__anon55716a6f0111::PragmaNoOpenMPHandler90*67e74705SXin Li PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
91*67e74705SXin Li void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
92*67e74705SXin Li Token &FirstToken) override;
93*67e74705SXin Li };
94*67e74705SXin Li
95*67e74705SXin Li struct PragmaOpenMPHandler : public PragmaHandler {
PragmaOpenMPHandler__anon55716a6f0111::PragmaOpenMPHandler96*67e74705SXin Li PragmaOpenMPHandler() : PragmaHandler("omp") { }
97*67e74705SXin Li void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
98*67e74705SXin Li Token &FirstToken) override;
99*67e74705SXin Li };
100*67e74705SXin Li
101*67e74705SXin Li /// PragmaCommentHandler - "\#pragma comment ...".
102*67e74705SXin Li struct PragmaCommentHandler : public PragmaHandler {
PragmaCommentHandler__anon55716a6f0111::PragmaCommentHandler103*67e74705SXin Li PragmaCommentHandler(Sema &Actions)
104*67e74705SXin Li : PragmaHandler("comment"), Actions(Actions) {}
105*67e74705SXin Li void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
106*67e74705SXin Li Token &FirstToken) override;
107*67e74705SXin Li private:
108*67e74705SXin Li Sema &Actions;
109*67e74705SXin Li };
110*67e74705SXin Li
111*67e74705SXin Li struct PragmaDetectMismatchHandler : public PragmaHandler {
PragmaDetectMismatchHandler__anon55716a6f0111::PragmaDetectMismatchHandler112*67e74705SXin Li PragmaDetectMismatchHandler(Sema &Actions)
113*67e74705SXin Li : PragmaHandler("detect_mismatch"), Actions(Actions) {}
114*67e74705SXin Li void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
115*67e74705SXin Li Token &FirstToken) override;
116*67e74705SXin Li private:
117*67e74705SXin Li Sema &Actions;
118*67e74705SXin Li };
119*67e74705SXin Li
120*67e74705SXin Li struct PragmaMSPointersToMembers : public PragmaHandler {
PragmaMSPointersToMembers__anon55716a6f0111::PragmaMSPointersToMembers121*67e74705SXin Li explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
122*67e74705SXin Li void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
123*67e74705SXin Li Token &FirstToken) override;
124*67e74705SXin Li };
125*67e74705SXin Li
126*67e74705SXin Li struct PragmaMSVtorDisp : public PragmaHandler {
PragmaMSVtorDisp__anon55716a6f0111::PragmaMSVtorDisp127*67e74705SXin Li explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
128*67e74705SXin Li void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
129*67e74705SXin Li Token &FirstToken) override;
130*67e74705SXin Li };
131*67e74705SXin Li
132*67e74705SXin Li struct PragmaMSPragma : public PragmaHandler {
PragmaMSPragma__anon55716a6f0111::PragmaMSPragma133*67e74705SXin Li explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
134*67e74705SXin Li void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
135*67e74705SXin Li Token &FirstToken) override;
136*67e74705SXin Li };
137*67e74705SXin Li
138*67e74705SXin Li /// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
139*67e74705SXin Li struct PragmaOptimizeHandler : public PragmaHandler {
PragmaOptimizeHandler__anon55716a6f0111::PragmaOptimizeHandler140*67e74705SXin Li PragmaOptimizeHandler(Sema &S)
141*67e74705SXin Li : PragmaHandler("optimize"), Actions(S) {}
142*67e74705SXin Li void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
143*67e74705SXin Li Token &FirstToken) override;
144*67e74705SXin Li private:
145*67e74705SXin Li Sema &Actions;
146*67e74705SXin Li };
147*67e74705SXin Li
148*67e74705SXin Li struct PragmaLoopHintHandler : public PragmaHandler {
PragmaLoopHintHandler__anon55716a6f0111::PragmaLoopHintHandler149*67e74705SXin Li PragmaLoopHintHandler() : PragmaHandler("loop") {}
150*67e74705SXin Li void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
151*67e74705SXin Li Token &FirstToken) override;
152*67e74705SXin Li };
153*67e74705SXin Li
154*67e74705SXin Li struct PragmaUnrollHintHandler : public PragmaHandler {
PragmaUnrollHintHandler__anon55716a6f0111::PragmaUnrollHintHandler155*67e74705SXin Li PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
156*67e74705SXin Li void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
157*67e74705SXin Li Token &FirstToken) override;
158*67e74705SXin Li };
159*67e74705SXin Li
160*67e74705SXin Li struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
PragmaMSRuntimeChecksHandler__anon55716a6f0111::PragmaMSRuntimeChecksHandler161*67e74705SXin Li PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
162*67e74705SXin Li };
163*67e74705SXin Li
164*67e74705SXin Li } // end namespace
165*67e74705SXin Li
initializePragmaHandlers()166*67e74705SXin Li void Parser::initializePragmaHandlers() {
167*67e74705SXin Li AlignHandler.reset(new PragmaAlignHandler());
168*67e74705SXin Li PP.AddPragmaHandler(AlignHandler.get());
169*67e74705SXin Li
170*67e74705SXin Li GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
171*67e74705SXin Li PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
172*67e74705SXin Li
173*67e74705SXin Li OptionsHandler.reset(new PragmaOptionsHandler());
174*67e74705SXin Li PP.AddPragmaHandler(OptionsHandler.get());
175*67e74705SXin Li
176*67e74705SXin Li PackHandler.reset(new PragmaPackHandler());
177*67e74705SXin Li PP.AddPragmaHandler(PackHandler.get());
178*67e74705SXin Li
179*67e74705SXin Li MSStructHandler.reset(new PragmaMSStructHandler());
180*67e74705SXin Li PP.AddPragmaHandler(MSStructHandler.get());
181*67e74705SXin Li
182*67e74705SXin Li UnusedHandler.reset(new PragmaUnusedHandler());
183*67e74705SXin Li PP.AddPragmaHandler(UnusedHandler.get());
184*67e74705SXin Li
185*67e74705SXin Li WeakHandler.reset(new PragmaWeakHandler());
186*67e74705SXin Li PP.AddPragmaHandler(WeakHandler.get());
187*67e74705SXin Li
188*67e74705SXin Li RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
189*67e74705SXin Li PP.AddPragmaHandler(RedefineExtnameHandler.get());
190*67e74705SXin Li
191*67e74705SXin Li FPContractHandler.reset(new PragmaFPContractHandler());
192*67e74705SXin Li PP.AddPragmaHandler("STDC", FPContractHandler.get());
193*67e74705SXin Li
194*67e74705SXin Li if (getLangOpts().OpenCL) {
195*67e74705SXin Li OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
196*67e74705SXin Li PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
197*67e74705SXin Li
198*67e74705SXin Li PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
199*67e74705SXin Li }
200*67e74705SXin Li if (getLangOpts().OpenMP)
201*67e74705SXin Li OpenMPHandler.reset(new PragmaOpenMPHandler());
202*67e74705SXin Li else
203*67e74705SXin Li OpenMPHandler.reset(new PragmaNoOpenMPHandler());
204*67e74705SXin Li PP.AddPragmaHandler(OpenMPHandler.get());
205*67e74705SXin Li
206*67e74705SXin Li if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
207*67e74705SXin Li MSCommentHandler.reset(new PragmaCommentHandler(Actions));
208*67e74705SXin Li PP.AddPragmaHandler(MSCommentHandler.get());
209*67e74705SXin Li }
210*67e74705SXin Li
211*67e74705SXin Li if (getLangOpts().MicrosoftExt) {
212*67e74705SXin Li MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
213*67e74705SXin Li PP.AddPragmaHandler(MSDetectMismatchHandler.get());
214*67e74705SXin Li MSPointersToMembers.reset(new PragmaMSPointersToMembers());
215*67e74705SXin Li PP.AddPragmaHandler(MSPointersToMembers.get());
216*67e74705SXin Li MSVtorDisp.reset(new PragmaMSVtorDisp());
217*67e74705SXin Li PP.AddPragmaHandler(MSVtorDisp.get());
218*67e74705SXin Li MSInitSeg.reset(new PragmaMSPragma("init_seg"));
219*67e74705SXin Li PP.AddPragmaHandler(MSInitSeg.get());
220*67e74705SXin Li MSDataSeg.reset(new PragmaMSPragma("data_seg"));
221*67e74705SXin Li PP.AddPragmaHandler(MSDataSeg.get());
222*67e74705SXin Li MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
223*67e74705SXin Li PP.AddPragmaHandler(MSBSSSeg.get());
224*67e74705SXin Li MSConstSeg.reset(new PragmaMSPragma("const_seg"));
225*67e74705SXin Li PP.AddPragmaHandler(MSConstSeg.get());
226*67e74705SXin Li MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
227*67e74705SXin Li PP.AddPragmaHandler(MSCodeSeg.get());
228*67e74705SXin Li MSSection.reset(new PragmaMSPragma("section"));
229*67e74705SXin Li PP.AddPragmaHandler(MSSection.get());
230*67e74705SXin Li MSRuntimeChecks.reset(new PragmaMSRuntimeChecksHandler());
231*67e74705SXin Li PP.AddPragmaHandler(MSRuntimeChecks.get());
232*67e74705SXin Li }
233*67e74705SXin Li
234*67e74705SXin Li OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
235*67e74705SXin Li PP.AddPragmaHandler("clang", OptimizeHandler.get());
236*67e74705SXin Li
237*67e74705SXin Li LoopHintHandler.reset(new PragmaLoopHintHandler());
238*67e74705SXin Li PP.AddPragmaHandler("clang", LoopHintHandler.get());
239*67e74705SXin Li
240*67e74705SXin Li UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll"));
241*67e74705SXin Li PP.AddPragmaHandler(UnrollHintHandler.get());
242*67e74705SXin Li
243*67e74705SXin Li NoUnrollHintHandler.reset(new PragmaUnrollHintHandler("nounroll"));
244*67e74705SXin Li PP.AddPragmaHandler(NoUnrollHintHandler.get());
245*67e74705SXin Li }
246*67e74705SXin Li
resetPragmaHandlers()247*67e74705SXin Li void Parser::resetPragmaHandlers() {
248*67e74705SXin Li // Remove the pragma handlers we installed.
249*67e74705SXin Li PP.RemovePragmaHandler(AlignHandler.get());
250*67e74705SXin Li AlignHandler.reset();
251*67e74705SXin Li PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
252*67e74705SXin Li GCCVisibilityHandler.reset();
253*67e74705SXin Li PP.RemovePragmaHandler(OptionsHandler.get());
254*67e74705SXin Li OptionsHandler.reset();
255*67e74705SXin Li PP.RemovePragmaHandler(PackHandler.get());
256*67e74705SXin Li PackHandler.reset();
257*67e74705SXin Li PP.RemovePragmaHandler(MSStructHandler.get());
258*67e74705SXin Li MSStructHandler.reset();
259*67e74705SXin Li PP.RemovePragmaHandler(UnusedHandler.get());
260*67e74705SXin Li UnusedHandler.reset();
261*67e74705SXin Li PP.RemovePragmaHandler(WeakHandler.get());
262*67e74705SXin Li WeakHandler.reset();
263*67e74705SXin Li PP.RemovePragmaHandler(RedefineExtnameHandler.get());
264*67e74705SXin Li RedefineExtnameHandler.reset();
265*67e74705SXin Li
266*67e74705SXin Li if (getLangOpts().OpenCL) {
267*67e74705SXin Li PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
268*67e74705SXin Li OpenCLExtensionHandler.reset();
269*67e74705SXin Li PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
270*67e74705SXin Li }
271*67e74705SXin Li PP.RemovePragmaHandler(OpenMPHandler.get());
272*67e74705SXin Li OpenMPHandler.reset();
273*67e74705SXin Li
274*67e74705SXin Li if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
275*67e74705SXin Li PP.RemovePragmaHandler(MSCommentHandler.get());
276*67e74705SXin Li MSCommentHandler.reset();
277*67e74705SXin Li }
278*67e74705SXin Li
279*67e74705SXin Li if (getLangOpts().MicrosoftExt) {
280*67e74705SXin Li PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
281*67e74705SXin Li MSDetectMismatchHandler.reset();
282*67e74705SXin Li PP.RemovePragmaHandler(MSPointersToMembers.get());
283*67e74705SXin Li MSPointersToMembers.reset();
284*67e74705SXin Li PP.RemovePragmaHandler(MSVtorDisp.get());
285*67e74705SXin Li MSVtorDisp.reset();
286*67e74705SXin Li PP.RemovePragmaHandler(MSInitSeg.get());
287*67e74705SXin Li MSInitSeg.reset();
288*67e74705SXin Li PP.RemovePragmaHandler(MSDataSeg.get());
289*67e74705SXin Li MSDataSeg.reset();
290*67e74705SXin Li PP.RemovePragmaHandler(MSBSSSeg.get());
291*67e74705SXin Li MSBSSSeg.reset();
292*67e74705SXin Li PP.RemovePragmaHandler(MSConstSeg.get());
293*67e74705SXin Li MSConstSeg.reset();
294*67e74705SXin Li PP.RemovePragmaHandler(MSCodeSeg.get());
295*67e74705SXin Li MSCodeSeg.reset();
296*67e74705SXin Li PP.RemovePragmaHandler(MSSection.get());
297*67e74705SXin Li MSSection.reset();
298*67e74705SXin Li PP.RemovePragmaHandler(MSRuntimeChecks.get());
299*67e74705SXin Li MSRuntimeChecks.reset();
300*67e74705SXin Li }
301*67e74705SXin Li
302*67e74705SXin Li PP.RemovePragmaHandler("STDC", FPContractHandler.get());
303*67e74705SXin Li FPContractHandler.reset();
304*67e74705SXin Li
305*67e74705SXin Li PP.RemovePragmaHandler("clang", OptimizeHandler.get());
306*67e74705SXin Li OptimizeHandler.reset();
307*67e74705SXin Li
308*67e74705SXin Li PP.RemovePragmaHandler("clang", LoopHintHandler.get());
309*67e74705SXin Li LoopHintHandler.reset();
310*67e74705SXin Li
311*67e74705SXin Li PP.RemovePragmaHandler(UnrollHintHandler.get());
312*67e74705SXin Li UnrollHintHandler.reset();
313*67e74705SXin Li
314*67e74705SXin Li PP.RemovePragmaHandler(NoUnrollHintHandler.get());
315*67e74705SXin Li NoUnrollHintHandler.reset();
316*67e74705SXin Li }
317*67e74705SXin Li
318*67e74705SXin Li /// \brief Handle the annotation token produced for #pragma unused(...)
319*67e74705SXin Li ///
320*67e74705SXin Li /// Each annot_pragma_unused is followed by the argument token so e.g.
321*67e74705SXin Li /// "#pragma unused(x,y)" becomes:
322*67e74705SXin Li /// annot_pragma_unused 'x' annot_pragma_unused 'y'
HandlePragmaUnused()323*67e74705SXin Li void Parser::HandlePragmaUnused() {
324*67e74705SXin Li assert(Tok.is(tok::annot_pragma_unused));
325*67e74705SXin Li SourceLocation UnusedLoc = ConsumeToken();
326*67e74705SXin Li Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
327*67e74705SXin Li ConsumeToken(); // The argument token.
328*67e74705SXin Li }
329*67e74705SXin Li
HandlePragmaVisibility()330*67e74705SXin Li void Parser::HandlePragmaVisibility() {
331*67e74705SXin Li assert(Tok.is(tok::annot_pragma_vis));
332*67e74705SXin Li const IdentifierInfo *VisType =
333*67e74705SXin Li static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
334*67e74705SXin Li SourceLocation VisLoc = ConsumeToken();
335*67e74705SXin Li Actions.ActOnPragmaVisibility(VisType, VisLoc);
336*67e74705SXin Li }
337*67e74705SXin Li
338*67e74705SXin Li namespace {
339*67e74705SXin Li struct PragmaPackInfo {
340*67e74705SXin Li Sema::PragmaMsStackAction Action;
341*67e74705SXin Li StringRef SlotLabel;
342*67e74705SXin Li Token Alignment;
343*67e74705SXin Li };
344*67e74705SXin Li } // end anonymous namespace
345*67e74705SXin Li
HandlePragmaPack()346*67e74705SXin Li void Parser::HandlePragmaPack() {
347*67e74705SXin Li assert(Tok.is(tok::annot_pragma_pack));
348*67e74705SXin Li PragmaPackInfo *Info =
349*67e74705SXin Li static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
350*67e74705SXin Li SourceLocation PragmaLoc = ConsumeToken();
351*67e74705SXin Li ExprResult Alignment;
352*67e74705SXin Li if (Info->Alignment.is(tok::numeric_constant)) {
353*67e74705SXin Li Alignment = Actions.ActOnNumericConstant(Info->Alignment);
354*67e74705SXin Li if (Alignment.isInvalid())
355*67e74705SXin Li return;
356*67e74705SXin Li }
357*67e74705SXin Li Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
358*67e74705SXin Li Alignment.get());
359*67e74705SXin Li }
360*67e74705SXin Li
HandlePragmaMSStruct()361*67e74705SXin Li void Parser::HandlePragmaMSStruct() {
362*67e74705SXin Li assert(Tok.is(tok::annot_pragma_msstruct));
363*67e74705SXin Li PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
364*67e74705SXin Li reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
365*67e74705SXin Li Actions.ActOnPragmaMSStruct(Kind);
366*67e74705SXin Li ConsumeToken(); // The annotation token.
367*67e74705SXin Li }
368*67e74705SXin Li
HandlePragmaAlign()369*67e74705SXin Li void Parser::HandlePragmaAlign() {
370*67e74705SXin Li assert(Tok.is(tok::annot_pragma_align));
371*67e74705SXin Li Sema::PragmaOptionsAlignKind Kind =
372*67e74705SXin Li static_cast<Sema::PragmaOptionsAlignKind>(
373*67e74705SXin Li reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
374*67e74705SXin Li SourceLocation PragmaLoc = ConsumeToken();
375*67e74705SXin Li Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
376*67e74705SXin Li }
377*67e74705SXin Li
HandlePragmaDump()378*67e74705SXin Li void Parser::HandlePragmaDump() {
379*67e74705SXin Li assert(Tok.is(tok::annot_pragma_dump));
380*67e74705SXin Li IdentifierInfo *II =
381*67e74705SXin Li reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
382*67e74705SXin Li Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
383*67e74705SXin Li ConsumeToken();
384*67e74705SXin Li }
385*67e74705SXin Li
HandlePragmaWeak()386*67e74705SXin Li void Parser::HandlePragmaWeak() {
387*67e74705SXin Li assert(Tok.is(tok::annot_pragma_weak));
388*67e74705SXin Li SourceLocation PragmaLoc = ConsumeToken();
389*67e74705SXin Li Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
390*67e74705SXin Li Tok.getLocation());
391*67e74705SXin Li ConsumeToken(); // The weak name.
392*67e74705SXin Li }
393*67e74705SXin Li
HandlePragmaWeakAlias()394*67e74705SXin Li void Parser::HandlePragmaWeakAlias() {
395*67e74705SXin Li assert(Tok.is(tok::annot_pragma_weakalias));
396*67e74705SXin Li SourceLocation PragmaLoc = ConsumeToken();
397*67e74705SXin Li IdentifierInfo *WeakName = Tok.getIdentifierInfo();
398*67e74705SXin Li SourceLocation WeakNameLoc = Tok.getLocation();
399*67e74705SXin Li ConsumeToken();
400*67e74705SXin Li IdentifierInfo *AliasName = Tok.getIdentifierInfo();
401*67e74705SXin Li SourceLocation AliasNameLoc = Tok.getLocation();
402*67e74705SXin Li ConsumeToken();
403*67e74705SXin Li Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
404*67e74705SXin Li WeakNameLoc, AliasNameLoc);
405*67e74705SXin Li
406*67e74705SXin Li }
407*67e74705SXin Li
HandlePragmaRedefineExtname()408*67e74705SXin Li void Parser::HandlePragmaRedefineExtname() {
409*67e74705SXin Li assert(Tok.is(tok::annot_pragma_redefine_extname));
410*67e74705SXin Li SourceLocation RedefLoc = ConsumeToken();
411*67e74705SXin Li IdentifierInfo *RedefName = Tok.getIdentifierInfo();
412*67e74705SXin Li SourceLocation RedefNameLoc = Tok.getLocation();
413*67e74705SXin Li ConsumeToken();
414*67e74705SXin Li IdentifierInfo *AliasName = Tok.getIdentifierInfo();
415*67e74705SXin Li SourceLocation AliasNameLoc = Tok.getLocation();
416*67e74705SXin Li ConsumeToken();
417*67e74705SXin Li Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
418*67e74705SXin Li RedefNameLoc, AliasNameLoc);
419*67e74705SXin Li }
420*67e74705SXin Li
HandlePragmaFPContract()421*67e74705SXin Li void Parser::HandlePragmaFPContract() {
422*67e74705SXin Li assert(Tok.is(tok::annot_pragma_fp_contract));
423*67e74705SXin Li tok::OnOffSwitch OOS =
424*67e74705SXin Li static_cast<tok::OnOffSwitch>(
425*67e74705SXin Li reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
426*67e74705SXin Li Actions.ActOnPragmaFPContract(OOS);
427*67e74705SXin Li ConsumeToken(); // The annotation token.
428*67e74705SXin Li }
429*67e74705SXin Li
HandlePragmaCaptured()430*67e74705SXin Li StmtResult Parser::HandlePragmaCaptured()
431*67e74705SXin Li {
432*67e74705SXin Li assert(Tok.is(tok::annot_pragma_captured));
433*67e74705SXin Li ConsumeToken();
434*67e74705SXin Li
435*67e74705SXin Li if (Tok.isNot(tok::l_brace)) {
436*67e74705SXin Li PP.Diag(Tok, diag::err_expected) << tok::l_brace;
437*67e74705SXin Li return StmtError();
438*67e74705SXin Li }
439*67e74705SXin Li
440*67e74705SXin Li SourceLocation Loc = Tok.getLocation();
441*67e74705SXin Li
442*67e74705SXin Li ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
443*67e74705SXin Li Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
444*67e74705SXin Li /*NumParams=*/1);
445*67e74705SXin Li
446*67e74705SXin Li StmtResult R = ParseCompoundStatement();
447*67e74705SXin Li CapturedRegionScope.Exit();
448*67e74705SXin Li
449*67e74705SXin Li if (R.isInvalid()) {
450*67e74705SXin Li Actions.ActOnCapturedRegionError();
451*67e74705SXin Li return StmtError();
452*67e74705SXin Li }
453*67e74705SXin Li
454*67e74705SXin Li return Actions.ActOnCapturedRegionEnd(R.get());
455*67e74705SXin Li }
456*67e74705SXin Li
457*67e74705SXin Li namespace {
458*67e74705SXin Li typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
459*67e74705SXin Li }
460*67e74705SXin Li
HandlePragmaOpenCLExtension()461*67e74705SXin Li void Parser::HandlePragmaOpenCLExtension() {
462*67e74705SXin Li assert(Tok.is(tok::annot_pragma_opencl_extension));
463*67e74705SXin Li OpenCLExtData data =
464*67e74705SXin Li OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
465*67e74705SXin Li unsigned state = data.getInt();
466*67e74705SXin Li IdentifierInfo *ename = data.getPointer();
467*67e74705SXin Li SourceLocation NameLoc = Tok.getLocation();
468*67e74705SXin Li ConsumeToken(); // The annotation token.
469*67e74705SXin Li
470*67e74705SXin Li OpenCLOptions &f = Actions.getOpenCLOptions();
471*67e74705SXin Li auto CLVer = getLangOpts().OpenCLVersion;
472*67e74705SXin Li auto &Supp = getTargetInfo().getSupportedOpenCLOpts();
473*67e74705SXin Li // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
474*67e74705SXin Li // overriding all previously issued extension directives, but only if the
475*67e74705SXin Li // behavior is set to disable."
476*67e74705SXin Li if (state == 0 && ename->isStr("all")) {
477*67e74705SXin Li #define OPENCLEXT(nm) \
478*67e74705SXin Li if (Supp.is_##nm##_supported_extension(CLVer)) \
479*67e74705SXin Li f.nm = 0;
480*67e74705SXin Li #include "clang/Basic/OpenCLExtensions.def"
481*67e74705SXin Li }
482*67e74705SXin Li #define OPENCLEXT(nm) else if (ename->isStr(#nm)) \
483*67e74705SXin Li if (Supp.is_##nm##_supported_extension(CLVer)) \
484*67e74705SXin Li f.nm = state; \
485*67e74705SXin Li else if (Supp.is_##nm##_supported_core(CLVer)) \
486*67e74705SXin Li PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << ename; \
487*67e74705SXin Li else \
488*67e74705SXin Li PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << ename;
489*67e74705SXin Li #include "clang/Basic/OpenCLExtensions.def"
490*67e74705SXin Li else {
491*67e74705SXin Li PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
492*67e74705SXin Li return;
493*67e74705SXin Li }
494*67e74705SXin Li }
495*67e74705SXin Li
HandlePragmaMSPointersToMembers()496*67e74705SXin Li void Parser::HandlePragmaMSPointersToMembers() {
497*67e74705SXin Li assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
498*67e74705SXin Li LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
499*67e74705SXin Li static_cast<LangOptions::PragmaMSPointersToMembersKind>(
500*67e74705SXin Li reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
501*67e74705SXin Li SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
502*67e74705SXin Li Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
503*67e74705SXin Li }
504*67e74705SXin Li
HandlePragmaMSVtorDisp()505*67e74705SXin Li void Parser::HandlePragmaMSVtorDisp() {
506*67e74705SXin Li assert(Tok.is(tok::annot_pragma_ms_vtordisp));
507*67e74705SXin Li uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
508*67e74705SXin Li Sema::PragmaMsStackAction Action =
509*67e74705SXin Li static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
510*67e74705SXin Li MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
511*67e74705SXin Li SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
512*67e74705SXin Li Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
513*67e74705SXin Li }
514*67e74705SXin Li
HandlePragmaMSPragma()515*67e74705SXin Li void Parser::HandlePragmaMSPragma() {
516*67e74705SXin Li assert(Tok.is(tok::annot_pragma_ms_pragma));
517*67e74705SXin Li // Grab the tokens out of the annotation and enter them into the stream.
518*67e74705SXin Li auto TheTokens =
519*67e74705SXin Li (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
520*67e74705SXin Li PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true);
521*67e74705SXin Li SourceLocation PragmaLocation = ConsumeToken(); // The annotation token.
522*67e74705SXin Li assert(Tok.isAnyIdentifier());
523*67e74705SXin Li StringRef PragmaName = Tok.getIdentifierInfo()->getName();
524*67e74705SXin Li PP.Lex(Tok); // pragma kind
525*67e74705SXin Li
526*67e74705SXin Li // Figure out which #pragma we're dealing with. The switch has no default
527*67e74705SXin Li // because lex shouldn't emit the annotation token for unrecognized pragmas.
528*67e74705SXin Li typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
529*67e74705SXin Li PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
530*67e74705SXin Li .Case("data_seg", &Parser::HandlePragmaMSSegment)
531*67e74705SXin Li .Case("bss_seg", &Parser::HandlePragmaMSSegment)
532*67e74705SXin Li .Case("const_seg", &Parser::HandlePragmaMSSegment)
533*67e74705SXin Li .Case("code_seg", &Parser::HandlePragmaMSSegment)
534*67e74705SXin Li .Case("section", &Parser::HandlePragmaMSSection)
535*67e74705SXin Li .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
536*67e74705SXin Li
537*67e74705SXin Li if (!(this->*Handler)(PragmaName, PragmaLocation)) {
538*67e74705SXin Li // Pragma handling failed, and has been diagnosed. Slurp up the tokens
539*67e74705SXin Li // until eof (really end of line) to prevent follow-on errors.
540*67e74705SXin Li while (Tok.isNot(tok::eof))
541*67e74705SXin Li PP.Lex(Tok);
542*67e74705SXin Li PP.Lex(Tok);
543*67e74705SXin Li }
544*67e74705SXin Li }
545*67e74705SXin Li
HandlePragmaMSSection(StringRef PragmaName,SourceLocation PragmaLocation)546*67e74705SXin Li bool Parser::HandlePragmaMSSection(StringRef PragmaName,
547*67e74705SXin Li SourceLocation PragmaLocation) {
548*67e74705SXin Li if (Tok.isNot(tok::l_paren)) {
549*67e74705SXin Li PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
550*67e74705SXin Li return false;
551*67e74705SXin Li }
552*67e74705SXin Li PP.Lex(Tok); // (
553*67e74705SXin Li // Parsing code for pragma section
554*67e74705SXin Li if (Tok.isNot(tok::string_literal)) {
555*67e74705SXin Li PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
556*67e74705SXin Li << PragmaName;
557*67e74705SXin Li return false;
558*67e74705SXin Li }
559*67e74705SXin Li ExprResult StringResult = ParseStringLiteralExpression();
560*67e74705SXin Li if (StringResult.isInvalid())
561*67e74705SXin Li return false; // Already diagnosed.
562*67e74705SXin Li StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
563*67e74705SXin Li if (SegmentName->getCharByteWidth() != 1) {
564*67e74705SXin Li PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
565*67e74705SXin Li << PragmaName;
566*67e74705SXin Li return false;
567*67e74705SXin Li }
568*67e74705SXin Li int SectionFlags = ASTContext::PSF_Read;
569*67e74705SXin Li bool SectionFlagsAreDefault = true;
570*67e74705SXin Li while (Tok.is(tok::comma)) {
571*67e74705SXin Li PP.Lex(Tok); // ,
572*67e74705SXin Li // Ignore "long" and "short".
573*67e74705SXin Li // They are undocumented, but widely used, section attributes which appear
574*67e74705SXin Li // to do nothing.
575*67e74705SXin Li if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
576*67e74705SXin Li PP.Lex(Tok); // long/short
577*67e74705SXin Li continue;
578*67e74705SXin Li }
579*67e74705SXin Li
580*67e74705SXin Li if (!Tok.isAnyIdentifier()) {
581*67e74705SXin Li PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
582*67e74705SXin Li << PragmaName;
583*67e74705SXin Li return false;
584*67e74705SXin Li }
585*67e74705SXin Li ASTContext::PragmaSectionFlag Flag =
586*67e74705SXin Li llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
587*67e74705SXin Li Tok.getIdentifierInfo()->getName())
588*67e74705SXin Li .Case("read", ASTContext::PSF_Read)
589*67e74705SXin Li .Case("write", ASTContext::PSF_Write)
590*67e74705SXin Li .Case("execute", ASTContext::PSF_Execute)
591*67e74705SXin Li .Case("shared", ASTContext::PSF_Invalid)
592*67e74705SXin Li .Case("nopage", ASTContext::PSF_Invalid)
593*67e74705SXin Li .Case("nocache", ASTContext::PSF_Invalid)
594*67e74705SXin Li .Case("discard", ASTContext::PSF_Invalid)
595*67e74705SXin Li .Case("remove", ASTContext::PSF_Invalid)
596*67e74705SXin Li .Default(ASTContext::PSF_None);
597*67e74705SXin Li if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
598*67e74705SXin Li PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
599*67e74705SXin Li ? diag::warn_pragma_invalid_specific_action
600*67e74705SXin Li : diag::warn_pragma_unsupported_action)
601*67e74705SXin Li << PragmaName << Tok.getIdentifierInfo()->getName();
602*67e74705SXin Li return false;
603*67e74705SXin Li }
604*67e74705SXin Li SectionFlags |= Flag;
605*67e74705SXin Li SectionFlagsAreDefault = false;
606*67e74705SXin Li PP.Lex(Tok); // Identifier
607*67e74705SXin Li }
608*67e74705SXin Li // If no section attributes are specified, the section will be marked as
609*67e74705SXin Li // read/write.
610*67e74705SXin Li if (SectionFlagsAreDefault)
611*67e74705SXin Li SectionFlags |= ASTContext::PSF_Write;
612*67e74705SXin Li if (Tok.isNot(tok::r_paren)) {
613*67e74705SXin Li PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
614*67e74705SXin Li return false;
615*67e74705SXin Li }
616*67e74705SXin Li PP.Lex(Tok); // )
617*67e74705SXin Li if (Tok.isNot(tok::eof)) {
618*67e74705SXin Li PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
619*67e74705SXin Li << PragmaName;
620*67e74705SXin Li return false;
621*67e74705SXin Li }
622*67e74705SXin Li PP.Lex(Tok); // eof
623*67e74705SXin Li Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
624*67e74705SXin Li return true;
625*67e74705SXin Li }
626*67e74705SXin Li
HandlePragmaMSSegment(StringRef PragmaName,SourceLocation PragmaLocation)627*67e74705SXin Li bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
628*67e74705SXin Li SourceLocation PragmaLocation) {
629*67e74705SXin Li if (Tok.isNot(tok::l_paren)) {
630*67e74705SXin Li PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
631*67e74705SXin Li return false;
632*67e74705SXin Li }
633*67e74705SXin Li PP.Lex(Tok); // (
634*67e74705SXin Li Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
635*67e74705SXin Li StringRef SlotLabel;
636*67e74705SXin Li if (Tok.isAnyIdentifier()) {
637*67e74705SXin Li StringRef PushPop = Tok.getIdentifierInfo()->getName();
638*67e74705SXin Li if (PushPop == "push")
639*67e74705SXin Li Action = Sema::PSK_Push;
640*67e74705SXin Li else if (PushPop == "pop")
641*67e74705SXin Li Action = Sema::PSK_Pop;
642*67e74705SXin Li else {
643*67e74705SXin Li PP.Diag(PragmaLocation,
644*67e74705SXin Li diag::warn_pragma_expected_section_push_pop_or_name)
645*67e74705SXin Li << PragmaName;
646*67e74705SXin Li return false;
647*67e74705SXin Li }
648*67e74705SXin Li if (Action != Sema::PSK_Reset) {
649*67e74705SXin Li PP.Lex(Tok); // push | pop
650*67e74705SXin Li if (Tok.is(tok::comma)) {
651*67e74705SXin Li PP.Lex(Tok); // ,
652*67e74705SXin Li // If we've got a comma, we either need a label or a string.
653*67e74705SXin Li if (Tok.isAnyIdentifier()) {
654*67e74705SXin Li SlotLabel = Tok.getIdentifierInfo()->getName();
655*67e74705SXin Li PP.Lex(Tok); // identifier
656*67e74705SXin Li if (Tok.is(tok::comma))
657*67e74705SXin Li PP.Lex(Tok);
658*67e74705SXin Li else if (Tok.isNot(tok::r_paren)) {
659*67e74705SXin Li PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
660*67e74705SXin Li << PragmaName;
661*67e74705SXin Li return false;
662*67e74705SXin Li }
663*67e74705SXin Li }
664*67e74705SXin Li } else if (Tok.isNot(tok::r_paren)) {
665*67e74705SXin Li PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
666*67e74705SXin Li return false;
667*67e74705SXin Li }
668*67e74705SXin Li }
669*67e74705SXin Li }
670*67e74705SXin Li // Grab the string literal for our section name.
671*67e74705SXin Li StringLiteral *SegmentName = nullptr;
672*67e74705SXin Li if (Tok.isNot(tok::r_paren)) {
673*67e74705SXin Li if (Tok.isNot(tok::string_literal)) {
674*67e74705SXin Li unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
675*67e74705SXin Li diag::warn_pragma_expected_section_name :
676*67e74705SXin Li diag::warn_pragma_expected_section_label_or_name :
677*67e74705SXin Li diag::warn_pragma_expected_section_push_pop_or_name;
678*67e74705SXin Li PP.Diag(PragmaLocation, DiagID) << PragmaName;
679*67e74705SXin Li return false;
680*67e74705SXin Li }
681*67e74705SXin Li ExprResult StringResult = ParseStringLiteralExpression();
682*67e74705SXin Li if (StringResult.isInvalid())
683*67e74705SXin Li return false; // Already diagnosed.
684*67e74705SXin Li SegmentName = cast<StringLiteral>(StringResult.get());
685*67e74705SXin Li if (SegmentName->getCharByteWidth() != 1) {
686*67e74705SXin Li PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
687*67e74705SXin Li << PragmaName;
688*67e74705SXin Li return false;
689*67e74705SXin Li }
690*67e74705SXin Li // Setting section "" has no effect
691*67e74705SXin Li if (SegmentName->getLength())
692*67e74705SXin Li Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
693*67e74705SXin Li }
694*67e74705SXin Li if (Tok.isNot(tok::r_paren)) {
695*67e74705SXin Li PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
696*67e74705SXin Li return false;
697*67e74705SXin Li }
698*67e74705SXin Li PP.Lex(Tok); // )
699*67e74705SXin Li if (Tok.isNot(tok::eof)) {
700*67e74705SXin Li PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
701*67e74705SXin Li << PragmaName;
702*67e74705SXin Li return false;
703*67e74705SXin Li }
704*67e74705SXin Li PP.Lex(Tok); // eof
705*67e74705SXin Li Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
706*67e74705SXin Li SegmentName, PragmaName);
707*67e74705SXin Li return true;
708*67e74705SXin Li }
709*67e74705SXin Li
710*67e74705SXin Li // #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
HandlePragmaMSInitSeg(StringRef PragmaName,SourceLocation PragmaLocation)711*67e74705SXin Li bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
712*67e74705SXin Li SourceLocation PragmaLocation) {
713*67e74705SXin Li if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
714*67e74705SXin Li PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
715*67e74705SXin Li return false;
716*67e74705SXin Li }
717*67e74705SXin Li
718*67e74705SXin Li if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
719*67e74705SXin Li PragmaName))
720*67e74705SXin Li return false;
721*67e74705SXin Li
722*67e74705SXin Li // Parse either the known section names or the string section name.
723*67e74705SXin Li StringLiteral *SegmentName = nullptr;
724*67e74705SXin Li if (Tok.isAnyIdentifier()) {
725*67e74705SXin Li auto *II = Tok.getIdentifierInfo();
726*67e74705SXin Li StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
727*67e74705SXin Li .Case("compiler", "\".CRT$XCC\"")
728*67e74705SXin Li .Case("lib", "\".CRT$XCL\"")
729*67e74705SXin Li .Case("user", "\".CRT$XCU\"")
730*67e74705SXin Li .Default("");
731*67e74705SXin Li
732*67e74705SXin Li if (!Section.empty()) {
733*67e74705SXin Li // Pretend the user wrote the appropriate string literal here.
734*67e74705SXin Li Token Toks[1];
735*67e74705SXin Li Toks[0].startToken();
736*67e74705SXin Li Toks[0].setKind(tok::string_literal);
737*67e74705SXin Li Toks[0].setLocation(Tok.getLocation());
738*67e74705SXin Li Toks[0].setLiteralData(Section.data());
739*67e74705SXin Li Toks[0].setLength(Section.size());
740*67e74705SXin Li SegmentName =
741*67e74705SXin Li cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
742*67e74705SXin Li PP.Lex(Tok);
743*67e74705SXin Li }
744*67e74705SXin Li } else if (Tok.is(tok::string_literal)) {
745*67e74705SXin Li ExprResult StringResult = ParseStringLiteralExpression();
746*67e74705SXin Li if (StringResult.isInvalid())
747*67e74705SXin Li return false;
748*67e74705SXin Li SegmentName = cast<StringLiteral>(StringResult.get());
749*67e74705SXin Li if (SegmentName->getCharByteWidth() != 1) {
750*67e74705SXin Li PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
751*67e74705SXin Li << PragmaName;
752*67e74705SXin Li return false;
753*67e74705SXin Li }
754*67e74705SXin Li // FIXME: Add support for the '[, func-name]' part of the pragma.
755*67e74705SXin Li }
756*67e74705SXin Li
757*67e74705SXin Li if (!SegmentName) {
758*67e74705SXin Li PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
759*67e74705SXin Li return false;
760*67e74705SXin Li }
761*67e74705SXin Li
762*67e74705SXin Li if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
763*67e74705SXin Li PragmaName) ||
764*67e74705SXin Li ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
765*67e74705SXin Li PragmaName))
766*67e74705SXin Li return false;
767*67e74705SXin Li
768*67e74705SXin Li Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
769*67e74705SXin Li return true;
770*67e74705SXin Li }
771*67e74705SXin Li
772*67e74705SXin Li namespace {
773*67e74705SXin Li struct PragmaLoopHintInfo {
774*67e74705SXin Li Token PragmaName;
775*67e74705SXin Li Token Option;
776*67e74705SXin Li ArrayRef<Token> Toks;
777*67e74705SXin Li };
778*67e74705SXin Li } // end anonymous namespace
779*67e74705SXin Li
PragmaLoopHintString(Token PragmaName,Token Option)780*67e74705SXin Li static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
781*67e74705SXin Li std::string PragmaString;
782*67e74705SXin Li if (PragmaName.getIdentifierInfo()->getName() == "loop") {
783*67e74705SXin Li PragmaString = "clang loop ";
784*67e74705SXin Li PragmaString += Option.getIdentifierInfo()->getName();
785*67e74705SXin Li } else {
786*67e74705SXin Li assert(PragmaName.getIdentifierInfo()->getName() == "unroll" &&
787*67e74705SXin Li "Unexpected pragma name");
788*67e74705SXin Li PragmaString = "unroll";
789*67e74705SXin Li }
790*67e74705SXin Li return PragmaString;
791*67e74705SXin Li }
792*67e74705SXin Li
HandlePragmaLoopHint(LoopHint & Hint)793*67e74705SXin Li bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
794*67e74705SXin Li assert(Tok.is(tok::annot_pragma_loop_hint));
795*67e74705SXin Li PragmaLoopHintInfo *Info =
796*67e74705SXin Li static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
797*67e74705SXin Li
798*67e74705SXin Li IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
799*67e74705SXin Li Hint.PragmaNameLoc = IdentifierLoc::create(
800*67e74705SXin Li Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
801*67e74705SXin Li
802*67e74705SXin Li // It is possible that the loop hint has no option identifier, such as
803*67e74705SXin Li // #pragma unroll(4).
804*67e74705SXin Li IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
805*67e74705SXin Li ? Info->Option.getIdentifierInfo()
806*67e74705SXin Li : nullptr;
807*67e74705SXin Li Hint.OptionLoc = IdentifierLoc::create(
808*67e74705SXin Li Actions.Context, Info->Option.getLocation(), OptionInfo);
809*67e74705SXin Li
810*67e74705SXin Li llvm::ArrayRef<Token> Toks = Info->Toks;
811*67e74705SXin Li
812*67e74705SXin Li // Return a valid hint if pragma unroll or nounroll were specified
813*67e74705SXin Li // without an argument.
814*67e74705SXin Li bool PragmaUnroll = PragmaNameInfo->getName() == "unroll";
815*67e74705SXin Li bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll";
816*67e74705SXin Li if (Toks.empty() && (PragmaUnroll || PragmaNoUnroll)) {
817*67e74705SXin Li ConsumeToken(); // The annotation token.
818*67e74705SXin Li Hint.Range = Info->PragmaName.getLocation();
819*67e74705SXin Li return true;
820*67e74705SXin Li }
821*67e74705SXin Li
822*67e74705SXin Li // The constant expression is always followed by an eof token, which increases
823*67e74705SXin Li // the TokSize by 1.
824*67e74705SXin Li assert(!Toks.empty() &&
825*67e74705SXin Li "PragmaLoopHintInfo::Toks must contain at least one token.");
826*67e74705SXin Li
827*67e74705SXin Li // If no option is specified the argument is assumed to be a constant expr.
828*67e74705SXin Li bool OptionUnroll = false;
829*67e74705SXin Li bool OptionDistribute = false;
830*67e74705SXin Li bool StateOption = false;
831*67e74705SXin Li if (OptionInfo) { // Pragma Unroll does not specify an option.
832*67e74705SXin Li OptionUnroll = OptionInfo->isStr("unroll");
833*67e74705SXin Li OptionDistribute = OptionInfo->isStr("distribute");
834*67e74705SXin Li StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
835*67e74705SXin Li .Case("vectorize", true)
836*67e74705SXin Li .Case("interleave", true)
837*67e74705SXin Li .Default(false) ||
838*67e74705SXin Li OptionUnroll || OptionDistribute;
839*67e74705SXin Li }
840*67e74705SXin Li
841*67e74705SXin Li bool AssumeSafetyArg = !OptionUnroll && !OptionDistribute;
842*67e74705SXin Li // Verify loop hint has an argument.
843*67e74705SXin Li if (Toks[0].is(tok::eof)) {
844*67e74705SXin Li ConsumeToken(); // The annotation token.
845*67e74705SXin Li Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
846*67e74705SXin Li << /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll
847*67e74705SXin Li << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
848*67e74705SXin Li return false;
849*67e74705SXin Li }
850*67e74705SXin Li
851*67e74705SXin Li // Validate the argument.
852*67e74705SXin Li if (StateOption) {
853*67e74705SXin Li ConsumeToken(); // The annotation token.
854*67e74705SXin Li SourceLocation StateLoc = Toks[0].getLocation();
855*67e74705SXin Li IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
856*67e74705SXin Li
857*67e74705SXin Li bool Valid = StateInfo &&
858*67e74705SXin Li llvm::StringSwitch<bool>(StateInfo->getName())
859*67e74705SXin Li .Cases("enable", "disable", true)
860*67e74705SXin Li .Case("full", OptionUnroll)
861*67e74705SXin Li .Case("assume_safety", AssumeSafetyArg)
862*67e74705SXin Li .Default(false);
863*67e74705SXin Li if (!Valid) {
864*67e74705SXin Li Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
865*67e74705SXin Li << /*FullKeyword=*/OptionUnroll
866*67e74705SXin Li << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
867*67e74705SXin Li return false;
868*67e74705SXin Li }
869*67e74705SXin Li if (Toks.size() > 2)
870*67e74705SXin Li Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
871*67e74705SXin Li << PragmaLoopHintString(Info->PragmaName, Info->Option);
872*67e74705SXin Li Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
873*67e74705SXin Li } else {
874*67e74705SXin Li // Enter constant expression including eof terminator into token stream.
875*67e74705SXin Li PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false);
876*67e74705SXin Li ConsumeToken(); // The annotation token.
877*67e74705SXin Li
878*67e74705SXin Li ExprResult R = ParseConstantExpression();
879*67e74705SXin Li
880*67e74705SXin Li // Tokens following an error in an ill-formed constant expression will
881*67e74705SXin Li // remain in the token stream and must be removed.
882*67e74705SXin Li if (Tok.isNot(tok::eof)) {
883*67e74705SXin Li Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
884*67e74705SXin Li << PragmaLoopHintString(Info->PragmaName, Info->Option);
885*67e74705SXin Li while (Tok.isNot(tok::eof))
886*67e74705SXin Li ConsumeAnyToken();
887*67e74705SXin Li }
888*67e74705SXin Li
889*67e74705SXin Li ConsumeToken(); // Consume the constant expression eof terminator.
890*67e74705SXin Li
891*67e74705SXin Li if (R.isInvalid() ||
892*67e74705SXin Li Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
893*67e74705SXin Li return false;
894*67e74705SXin Li
895*67e74705SXin Li // Argument is a constant expression with an integer type.
896*67e74705SXin Li Hint.ValueExpr = R.get();
897*67e74705SXin Li }
898*67e74705SXin Li
899*67e74705SXin Li Hint.Range = SourceRange(Info->PragmaName.getLocation(),
900*67e74705SXin Li Info->Toks.back().getLocation());
901*67e74705SXin Li return true;
902*67e74705SXin Li }
903*67e74705SXin Li
904*67e74705SXin Li // #pragma GCC visibility comes in two variants:
905*67e74705SXin Li // 'push' '(' [visibility] ')'
906*67e74705SXin Li // 'pop'
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & VisTok)907*67e74705SXin Li void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
908*67e74705SXin Li PragmaIntroducerKind Introducer,
909*67e74705SXin Li Token &VisTok) {
910*67e74705SXin Li SourceLocation VisLoc = VisTok.getLocation();
911*67e74705SXin Li
912*67e74705SXin Li Token Tok;
913*67e74705SXin Li PP.LexUnexpandedToken(Tok);
914*67e74705SXin Li
915*67e74705SXin Li const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
916*67e74705SXin Li
917*67e74705SXin Li const IdentifierInfo *VisType;
918*67e74705SXin Li if (PushPop && PushPop->isStr("pop")) {
919*67e74705SXin Li VisType = nullptr;
920*67e74705SXin Li } else if (PushPop && PushPop->isStr("push")) {
921*67e74705SXin Li PP.LexUnexpandedToken(Tok);
922*67e74705SXin Li if (Tok.isNot(tok::l_paren)) {
923*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
924*67e74705SXin Li << "visibility";
925*67e74705SXin Li return;
926*67e74705SXin Li }
927*67e74705SXin Li PP.LexUnexpandedToken(Tok);
928*67e74705SXin Li VisType = Tok.getIdentifierInfo();
929*67e74705SXin Li if (!VisType) {
930*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
931*67e74705SXin Li << "visibility";
932*67e74705SXin Li return;
933*67e74705SXin Li }
934*67e74705SXin Li PP.LexUnexpandedToken(Tok);
935*67e74705SXin Li if (Tok.isNot(tok::r_paren)) {
936*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
937*67e74705SXin Li << "visibility";
938*67e74705SXin Li return;
939*67e74705SXin Li }
940*67e74705SXin Li } else {
941*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
942*67e74705SXin Li << "visibility";
943*67e74705SXin Li return;
944*67e74705SXin Li }
945*67e74705SXin Li SourceLocation EndLoc = Tok.getLocation();
946*67e74705SXin Li PP.LexUnexpandedToken(Tok);
947*67e74705SXin Li if (Tok.isNot(tok::eod)) {
948*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
949*67e74705SXin Li << "visibility";
950*67e74705SXin Li return;
951*67e74705SXin Li }
952*67e74705SXin Li
953*67e74705SXin Li auto Toks = llvm::make_unique<Token[]>(1);
954*67e74705SXin Li Toks[0].startToken();
955*67e74705SXin Li Toks[0].setKind(tok::annot_pragma_vis);
956*67e74705SXin Li Toks[0].setLocation(VisLoc);
957*67e74705SXin Li Toks[0].setAnnotationEndLoc(EndLoc);
958*67e74705SXin Li Toks[0].setAnnotationValue(
959*67e74705SXin Li const_cast<void*>(static_cast<const void*>(VisType)));
960*67e74705SXin Li PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true);
961*67e74705SXin Li }
962*67e74705SXin Li
963*67e74705SXin Li // #pragma pack(...) comes in the following delicious flavors:
964*67e74705SXin Li // pack '(' [integer] ')'
965*67e74705SXin Li // pack '(' 'show' ')'
966*67e74705SXin Li // pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & PackTok)967*67e74705SXin Li void PragmaPackHandler::HandlePragma(Preprocessor &PP,
968*67e74705SXin Li PragmaIntroducerKind Introducer,
969*67e74705SXin Li Token &PackTok) {
970*67e74705SXin Li SourceLocation PackLoc = PackTok.getLocation();
971*67e74705SXin Li
972*67e74705SXin Li Token Tok;
973*67e74705SXin Li PP.Lex(Tok);
974*67e74705SXin Li if (Tok.isNot(tok::l_paren)) {
975*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
976*67e74705SXin Li return;
977*67e74705SXin Li }
978*67e74705SXin Li
979*67e74705SXin Li Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
980*67e74705SXin Li StringRef SlotLabel;
981*67e74705SXin Li Token Alignment;
982*67e74705SXin Li Alignment.startToken();
983*67e74705SXin Li PP.Lex(Tok);
984*67e74705SXin Li if (Tok.is(tok::numeric_constant)) {
985*67e74705SXin Li Alignment = Tok;
986*67e74705SXin Li
987*67e74705SXin Li PP.Lex(Tok);
988*67e74705SXin Li
989*67e74705SXin Li // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
990*67e74705SXin Li // the push/pop stack.
991*67e74705SXin Li // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
992*67e74705SXin Li Action =
993*67e74705SXin Li PP.getLangOpts().ApplePragmaPack ? Sema::PSK_Push_Set : Sema::PSK_Set;
994*67e74705SXin Li } else if (Tok.is(tok::identifier)) {
995*67e74705SXin Li const IdentifierInfo *II = Tok.getIdentifierInfo();
996*67e74705SXin Li if (II->isStr("show")) {
997*67e74705SXin Li Action = Sema::PSK_Show;
998*67e74705SXin Li PP.Lex(Tok);
999*67e74705SXin Li } else {
1000*67e74705SXin Li if (II->isStr("push")) {
1001*67e74705SXin Li Action = Sema::PSK_Push;
1002*67e74705SXin Li } else if (II->isStr("pop")) {
1003*67e74705SXin Li Action = Sema::PSK_Pop;
1004*67e74705SXin Li } else {
1005*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
1006*67e74705SXin Li return;
1007*67e74705SXin Li }
1008*67e74705SXin Li PP.Lex(Tok);
1009*67e74705SXin Li
1010*67e74705SXin Li if (Tok.is(tok::comma)) {
1011*67e74705SXin Li PP.Lex(Tok);
1012*67e74705SXin Li
1013*67e74705SXin Li if (Tok.is(tok::numeric_constant)) {
1014*67e74705SXin Li Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
1015*67e74705SXin Li Alignment = Tok;
1016*67e74705SXin Li
1017*67e74705SXin Li PP.Lex(Tok);
1018*67e74705SXin Li } else if (Tok.is(tok::identifier)) {
1019*67e74705SXin Li SlotLabel = Tok.getIdentifierInfo()->getName();
1020*67e74705SXin Li PP.Lex(Tok);
1021*67e74705SXin Li
1022*67e74705SXin Li if (Tok.is(tok::comma)) {
1023*67e74705SXin Li PP.Lex(Tok);
1024*67e74705SXin Li
1025*67e74705SXin Li if (Tok.isNot(tok::numeric_constant)) {
1026*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
1027*67e74705SXin Li return;
1028*67e74705SXin Li }
1029*67e74705SXin Li
1030*67e74705SXin Li Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
1031*67e74705SXin Li Alignment = Tok;
1032*67e74705SXin Li
1033*67e74705SXin Li PP.Lex(Tok);
1034*67e74705SXin Li }
1035*67e74705SXin Li } else {
1036*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
1037*67e74705SXin Li return;
1038*67e74705SXin Li }
1039*67e74705SXin Li }
1040*67e74705SXin Li }
1041*67e74705SXin Li } else if (PP.getLangOpts().ApplePragmaPack) {
1042*67e74705SXin Li // In MSVC/gcc, #pragma pack() resets the alignment without affecting
1043*67e74705SXin Li // the push/pop stack.
1044*67e74705SXin Li // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
1045*67e74705SXin Li Action = Sema::PSK_Pop;
1046*67e74705SXin Li }
1047*67e74705SXin Li
1048*67e74705SXin Li if (Tok.isNot(tok::r_paren)) {
1049*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
1050*67e74705SXin Li return;
1051*67e74705SXin Li }
1052*67e74705SXin Li
1053*67e74705SXin Li SourceLocation RParenLoc = Tok.getLocation();
1054*67e74705SXin Li PP.Lex(Tok);
1055*67e74705SXin Li if (Tok.isNot(tok::eod)) {
1056*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
1057*67e74705SXin Li return;
1058*67e74705SXin Li }
1059*67e74705SXin Li
1060*67e74705SXin Li PragmaPackInfo *Info =
1061*67e74705SXin Li PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
1062*67e74705SXin Li Info->Action = Action;
1063*67e74705SXin Li Info->SlotLabel = SlotLabel;
1064*67e74705SXin Li Info->Alignment = Alignment;
1065*67e74705SXin Li
1066*67e74705SXin Li MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1067*67e74705SXin Li 1);
1068*67e74705SXin Li Toks[0].startToken();
1069*67e74705SXin Li Toks[0].setKind(tok::annot_pragma_pack);
1070*67e74705SXin Li Toks[0].setLocation(PackLoc);
1071*67e74705SXin Li Toks[0].setAnnotationEndLoc(RParenLoc);
1072*67e74705SXin Li Toks[0].setAnnotationValue(static_cast<void*>(Info));
1073*67e74705SXin Li PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
1074*67e74705SXin Li }
1075*67e74705SXin Li
1076*67e74705SXin Li // #pragma ms_struct on
1077*67e74705SXin Li // #pragma ms_struct off
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & MSStructTok)1078*67e74705SXin Li void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
1079*67e74705SXin Li PragmaIntroducerKind Introducer,
1080*67e74705SXin Li Token &MSStructTok) {
1081*67e74705SXin Li PragmaMSStructKind Kind = PMSST_OFF;
1082*67e74705SXin Li
1083*67e74705SXin Li Token Tok;
1084*67e74705SXin Li PP.Lex(Tok);
1085*67e74705SXin Li if (Tok.isNot(tok::identifier)) {
1086*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1087*67e74705SXin Li return;
1088*67e74705SXin Li }
1089*67e74705SXin Li SourceLocation EndLoc = Tok.getLocation();
1090*67e74705SXin Li const IdentifierInfo *II = Tok.getIdentifierInfo();
1091*67e74705SXin Li if (II->isStr("on")) {
1092*67e74705SXin Li Kind = PMSST_ON;
1093*67e74705SXin Li PP.Lex(Tok);
1094*67e74705SXin Li }
1095*67e74705SXin Li else if (II->isStr("off") || II->isStr("reset"))
1096*67e74705SXin Li PP.Lex(Tok);
1097*67e74705SXin Li else {
1098*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1099*67e74705SXin Li return;
1100*67e74705SXin Li }
1101*67e74705SXin Li
1102*67e74705SXin Li if (Tok.isNot(tok::eod)) {
1103*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1104*67e74705SXin Li << "ms_struct";
1105*67e74705SXin Li return;
1106*67e74705SXin Li }
1107*67e74705SXin Li
1108*67e74705SXin Li MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1109*67e74705SXin Li 1);
1110*67e74705SXin Li Toks[0].startToken();
1111*67e74705SXin Li Toks[0].setKind(tok::annot_pragma_msstruct);
1112*67e74705SXin Li Toks[0].setLocation(MSStructTok.getLocation());
1113*67e74705SXin Li Toks[0].setAnnotationEndLoc(EndLoc);
1114*67e74705SXin Li Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1115*67e74705SXin Li static_cast<uintptr_t>(Kind)));
1116*67e74705SXin Li PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
1117*67e74705SXin Li }
1118*67e74705SXin Li
1119*67e74705SXin Li // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
1120*67e74705SXin Li // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
ParseAlignPragma(Preprocessor & PP,Token & FirstTok,bool IsOptions)1121*67e74705SXin Li static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
1122*67e74705SXin Li bool IsOptions) {
1123*67e74705SXin Li Token Tok;
1124*67e74705SXin Li
1125*67e74705SXin Li if (IsOptions) {
1126*67e74705SXin Li PP.Lex(Tok);
1127*67e74705SXin Li if (Tok.isNot(tok::identifier) ||
1128*67e74705SXin Li !Tok.getIdentifierInfo()->isStr("align")) {
1129*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
1130*67e74705SXin Li return;
1131*67e74705SXin Li }
1132*67e74705SXin Li }
1133*67e74705SXin Li
1134*67e74705SXin Li PP.Lex(Tok);
1135*67e74705SXin Li if (Tok.isNot(tok::equal)) {
1136*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
1137*67e74705SXin Li << IsOptions;
1138*67e74705SXin Li return;
1139*67e74705SXin Li }
1140*67e74705SXin Li
1141*67e74705SXin Li PP.Lex(Tok);
1142*67e74705SXin Li if (Tok.isNot(tok::identifier)) {
1143*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1144*67e74705SXin Li << (IsOptions ? "options" : "align");
1145*67e74705SXin Li return;
1146*67e74705SXin Li }
1147*67e74705SXin Li
1148*67e74705SXin Li Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
1149*67e74705SXin Li const IdentifierInfo *II = Tok.getIdentifierInfo();
1150*67e74705SXin Li if (II->isStr("native"))
1151*67e74705SXin Li Kind = Sema::POAK_Native;
1152*67e74705SXin Li else if (II->isStr("natural"))
1153*67e74705SXin Li Kind = Sema::POAK_Natural;
1154*67e74705SXin Li else if (II->isStr("packed"))
1155*67e74705SXin Li Kind = Sema::POAK_Packed;
1156*67e74705SXin Li else if (II->isStr("power"))
1157*67e74705SXin Li Kind = Sema::POAK_Power;
1158*67e74705SXin Li else if (II->isStr("mac68k"))
1159*67e74705SXin Li Kind = Sema::POAK_Mac68k;
1160*67e74705SXin Li else if (II->isStr("reset"))
1161*67e74705SXin Li Kind = Sema::POAK_Reset;
1162*67e74705SXin Li else {
1163*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
1164*67e74705SXin Li << IsOptions;
1165*67e74705SXin Li return;
1166*67e74705SXin Li }
1167*67e74705SXin Li
1168*67e74705SXin Li SourceLocation EndLoc = Tok.getLocation();
1169*67e74705SXin Li PP.Lex(Tok);
1170*67e74705SXin Li if (Tok.isNot(tok::eod)) {
1171*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1172*67e74705SXin Li << (IsOptions ? "options" : "align");
1173*67e74705SXin Li return;
1174*67e74705SXin Li }
1175*67e74705SXin Li
1176*67e74705SXin Li MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1177*67e74705SXin Li 1);
1178*67e74705SXin Li Toks[0].startToken();
1179*67e74705SXin Li Toks[0].setKind(tok::annot_pragma_align);
1180*67e74705SXin Li Toks[0].setLocation(FirstTok.getLocation());
1181*67e74705SXin Li Toks[0].setAnnotationEndLoc(EndLoc);
1182*67e74705SXin Li Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1183*67e74705SXin Li static_cast<uintptr_t>(Kind)));
1184*67e74705SXin Li PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
1185*67e74705SXin Li }
1186*67e74705SXin Li
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & AlignTok)1187*67e74705SXin Li void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
1188*67e74705SXin Li PragmaIntroducerKind Introducer,
1189*67e74705SXin Li Token &AlignTok) {
1190*67e74705SXin Li ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
1191*67e74705SXin Li }
1192*67e74705SXin Li
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & OptionsTok)1193*67e74705SXin Li void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
1194*67e74705SXin Li PragmaIntroducerKind Introducer,
1195*67e74705SXin Li Token &OptionsTok) {
1196*67e74705SXin Li ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
1197*67e74705SXin Li }
1198*67e74705SXin Li
1199*67e74705SXin Li // #pragma unused(identifier)
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & UnusedTok)1200*67e74705SXin Li void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
1201*67e74705SXin Li PragmaIntroducerKind Introducer,
1202*67e74705SXin Li Token &UnusedTok) {
1203*67e74705SXin Li // FIXME: Should we be expanding macros here? My guess is no.
1204*67e74705SXin Li SourceLocation UnusedLoc = UnusedTok.getLocation();
1205*67e74705SXin Li
1206*67e74705SXin Li // Lex the left '('.
1207*67e74705SXin Li Token Tok;
1208*67e74705SXin Li PP.Lex(Tok);
1209*67e74705SXin Li if (Tok.isNot(tok::l_paren)) {
1210*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
1211*67e74705SXin Li return;
1212*67e74705SXin Li }
1213*67e74705SXin Li
1214*67e74705SXin Li // Lex the declaration reference(s).
1215*67e74705SXin Li SmallVector<Token, 5> Identifiers;
1216*67e74705SXin Li SourceLocation RParenLoc;
1217*67e74705SXin Li bool LexID = true;
1218*67e74705SXin Li
1219*67e74705SXin Li while (true) {
1220*67e74705SXin Li PP.Lex(Tok);
1221*67e74705SXin Li
1222*67e74705SXin Li if (LexID) {
1223*67e74705SXin Li if (Tok.is(tok::identifier)) {
1224*67e74705SXin Li Identifiers.push_back(Tok);
1225*67e74705SXin Li LexID = false;
1226*67e74705SXin Li continue;
1227*67e74705SXin Li }
1228*67e74705SXin Li
1229*67e74705SXin Li // Illegal token!
1230*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
1231*67e74705SXin Li return;
1232*67e74705SXin Li }
1233*67e74705SXin Li
1234*67e74705SXin Li // We are execting a ')' or a ','.
1235*67e74705SXin Li if (Tok.is(tok::comma)) {
1236*67e74705SXin Li LexID = true;
1237*67e74705SXin Li continue;
1238*67e74705SXin Li }
1239*67e74705SXin Li
1240*67e74705SXin Li if (Tok.is(tok::r_paren)) {
1241*67e74705SXin Li RParenLoc = Tok.getLocation();
1242*67e74705SXin Li break;
1243*67e74705SXin Li }
1244*67e74705SXin Li
1245*67e74705SXin Li // Illegal token!
1246*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
1247*67e74705SXin Li return;
1248*67e74705SXin Li }
1249*67e74705SXin Li
1250*67e74705SXin Li PP.Lex(Tok);
1251*67e74705SXin Li if (Tok.isNot(tok::eod)) {
1252*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1253*67e74705SXin Li "unused";
1254*67e74705SXin Li return;
1255*67e74705SXin Li }
1256*67e74705SXin Li
1257*67e74705SXin Li // Verify that we have a location for the right parenthesis.
1258*67e74705SXin Li assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
1259*67e74705SXin Li assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
1260*67e74705SXin Li
1261*67e74705SXin Li // For each identifier token, insert into the token stream a
1262*67e74705SXin Li // annot_pragma_unused token followed by the identifier token.
1263*67e74705SXin Li // This allows us to cache a "#pragma unused" that occurs inside an inline
1264*67e74705SXin Li // C++ member function.
1265*67e74705SXin Li
1266*67e74705SXin Li MutableArrayRef<Token> Toks(
1267*67e74705SXin Li PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
1268*67e74705SXin Li 2 * Identifiers.size());
1269*67e74705SXin Li for (unsigned i=0; i != Identifiers.size(); i++) {
1270*67e74705SXin Li Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
1271*67e74705SXin Li pragmaUnusedTok.startToken();
1272*67e74705SXin Li pragmaUnusedTok.setKind(tok::annot_pragma_unused);
1273*67e74705SXin Li pragmaUnusedTok.setLocation(UnusedLoc);
1274*67e74705SXin Li idTok = Identifiers[i];
1275*67e74705SXin Li }
1276*67e74705SXin Li PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
1277*67e74705SXin Li }
1278*67e74705SXin Li
1279*67e74705SXin Li // #pragma weak identifier
1280*67e74705SXin Li // #pragma weak identifier '=' identifier
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & WeakTok)1281*67e74705SXin Li void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
1282*67e74705SXin Li PragmaIntroducerKind Introducer,
1283*67e74705SXin Li Token &WeakTok) {
1284*67e74705SXin Li SourceLocation WeakLoc = WeakTok.getLocation();
1285*67e74705SXin Li
1286*67e74705SXin Li Token Tok;
1287*67e74705SXin Li PP.Lex(Tok);
1288*67e74705SXin Li if (Tok.isNot(tok::identifier)) {
1289*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
1290*67e74705SXin Li return;
1291*67e74705SXin Li }
1292*67e74705SXin Li
1293*67e74705SXin Li Token WeakName = Tok;
1294*67e74705SXin Li bool HasAlias = false;
1295*67e74705SXin Li Token AliasName;
1296*67e74705SXin Li
1297*67e74705SXin Li PP.Lex(Tok);
1298*67e74705SXin Li if (Tok.is(tok::equal)) {
1299*67e74705SXin Li HasAlias = true;
1300*67e74705SXin Li PP.Lex(Tok);
1301*67e74705SXin Li if (Tok.isNot(tok::identifier)) {
1302*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1303*67e74705SXin Li << "weak";
1304*67e74705SXin Li return;
1305*67e74705SXin Li }
1306*67e74705SXin Li AliasName = Tok;
1307*67e74705SXin Li PP.Lex(Tok);
1308*67e74705SXin Li }
1309*67e74705SXin Li
1310*67e74705SXin Li if (Tok.isNot(tok::eod)) {
1311*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
1312*67e74705SXin Li return;
1313*67e74705SXin Li }
1314*67e74705SXin Li
1315*67e74705SXin Li if (HasAlias) {
1316*67e74705SXin Li MutableArrayRef<Token> Toks(
1317*67e74705SXin Li PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
1318*67e74705SXin Li Token &pragmaUnusedTok = Toks[0];
1319*67e74705SXin Li pragmaUnusedTok.startToken();
1320*67e74705SXin Li pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
1321*67e74705SXin Li pragmaUnusedTok.setLocation(WeakLoc);
1322*67e74705SXin Li pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
1323*67e74705SXin Li Toks[1] = WeakName;
1324*67e74705SXin Li Toks[2] = AliasName;
1325*67e74705SXin Li PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
1326*67e74705SXin Li } else {
1327*67e74705SXin Li MutableArrayRef<Token> Toks(
1328*67e74705SXin Li PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
1329*67e74705SXin Li Token &pragmaUnusedTok = Toks[0];
1330*67e74705SXin Li pragmaUnusedTok.startToken();
1331*67e74705SXin Li pragmaUnusedTok.setKind(tok::annot_pragma_weak);
1332*67e74705SXin Li pragmaUnusedTok.setLocation(WeakLoc);
1333*67e74705SXin Li pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
1334*67e74705SXin Li Toks[1] = WeakName;
1335*67e74705SXin Li PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
1336*67e74705SXin Li }
1337*67e74705SXin Li }
1338*67e74705SXin Li
1339*67e74705SXin Li // #pragma redefine_extname identifier identifier
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & RedefToken)1340*67e74705SXin Li void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
1341*67e74705SXin Li PragmaIntroducerKind Introducer,
1342*67e74705SXin Li Token &RedefToken) {
1343*67e74705SXin Li SourceLocation RedefLoc = RedefToken.getLocation();
1344*67e74705SXin Li
1345*67e74705SXin Li Token Tok;
1346*67e74705SXin Li PP.Lex(Tok);
1347*67e74705SXin Li if (Tok.isNot(tok::identifier)) {
1348*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1349*67e74705SXin Li "redefine_extname";
1350*67e74705SXin Li return;
1351*67e74705SXin Li }
1352*67e74705SXin Li
1353*67e74705SXin Li Token RedefName = Tok;
1354*67e74705SXin Li PP.Lex(Tok);
1355*67e74705SXin Li
1356*67e74705SXin Li if (Tok.isNot(tok::identifier)) {
1357*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1358*67e74705SXin Li << "redefine_extname";
1359*67e74705SXin Li return;
1360*67e74705SXin Li }
1361*67e74705SXin Li
1362*67e74705SXin Li Token AliasName = Tok;
1363*67e74705SXin Li PP.Lex(Tok);
1364*67e74705SXin Li
1365*67e74705SXin Li if (Tok.isNot(tok::eod)) {
1366*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1367*67e74705SXin Li "redefine_extname";
1368*67e74705SXin Li return;
1369*67e74705SXin Li }
1370*67e74705SXin Li
1371*67e74705SXin Li MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),
1372*67e74705SXin Li 3);
1373*67e74705SXin Li Token &pragmaRedefTok = Toks[0];
1374*67e74705SXin Li pragmaRedefTok.startToken();
1375*67e74705SXin Li pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
1376*67e74705SXin Li pragmaRedefTok.setLocation(RedefLoc);
1377*67e74705SXin Li pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
1378*67e74705SXin Li Toks[1] = RedefName;
1379*67e74705SXin Li Toks[2] = AliasName;
1380*67e74705SXin Li PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
1381*67e74705SXin Li }
1382*67e74705SXin Li
1383*67e74705SXin Li
1384*67e74705SXin Li void
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1385*67e74705SXin Li PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
1386*67e74705SXin Li PragmaIntroducerKind Introducer,
1387*67e74705SXin Li Token &Tok) {
1388*67e74705SXin Li tok::OnOffSwitch OOS;
1389*67e74705SXin Li if (PP.LexOnOffSwitch(OOS))
1390*67e74705SXin Li return;
1391*67e74705SXin Li
1392*67e74705SXin Li MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1393*67e74705SXin Li 1);
1394*67e74705SXin Li Toks[0].startToken();
1395*67e74705SXin Li Toks[0].setKind(tok::annot_pragma_fp_contract);
1396*67e74705SXin Li Toks[0].setLocation(Tok.getLocation());
1397*67e74705SXin Li Toks[0].setAnnotationEndLoc(Tok.getLocation());
1398*67e74705SXin Li Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1399*67e74705SXin Li static_cast<uintptr_t>(OOS)));
1400*67e74705SXin Li PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
1401*67e74705SXin Li }
1402*67e74705SXin Li
1403*67e74705SXin Li void
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1404*67e74705SXin Li PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
1405*67e74705SXin Li PragmaIntroducerKind Introducer,
1406*67e74705SXin Li Token &Tok) {
1407*67e74705SXin Li PP.LexUnexpandedToken(Tok);
1408*67e74705SXin Li if (Tok.isNot(tok::identifier)) {
1409*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1410*67e74705SXin Li "OPENCL";
1411*67e74705SXin Li return;
1412*67e74705SXin Li }
1413*67e74705SXin Li IdentifierInfo *ename = Tok.getIdentifierInfo();
1414*67e74705SXin Li SourceLocation NameLoc = Tok.getLocation();
1415*67e74705SXin Li
1416*67e74705SXin Li PP.Lex(Tok);
1417*67e74705SXin Li if (Tok.isNot(tok::colon)) {
1418*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
1419*67e74705SXin Li return;
1420*67e74705SXin Li }
1421*67e74705SXin Li
1422*67e74705SXin Li PP.Lex(Tok);
1423*67e74705SXin Li if (Tok.isNot(tok::identifier)) {
1424*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1425*67e74705SXin Li return;
1426*67e74705SXin Li }
1427*67e74705SXin Li IdentifierInfo *op = Tok.getIdentifierInfo();
1428*67e74705SXin Li
1429*67e74705SXin Li unsigned state;
1430*67e74705SXin Li if (op->isStr("enable")) {
1431*67e74705SXin Li state = 1;
1432*67e74705SXin Li } else if (op->isStr("disable")) {
1433*67e74705SXin Li state = 0;
1434*67e74705SXin Li } else {
1435*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1436*67e74705SXin Li return;
1437*67e74705SXin Li }
1438*67e74705SXin Li SourceLocation StateLoc = Tok.getLocation();
1439*67e74705SXin Li
1440*67e74705SXin Li PP.Lex(Tok);
1441*67e74705SXin Li if (Tok.isNot(tok::eod)) {
1442*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1443*67e74705SXin Li "OPENCL EXTENSION";
1444*67e74705SXin Li return;
1445*67e74705SXin Li }
1446*67e74705SXin Li
1447*67e74705SXin Li OpenCLExtData data(ename, state);
1448*67e74705SXin Li MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1449*67e74705SXin Li 1);
1450*67e74705SXin Li Toks[0].startToken();
1451*67e74705SXin Li Toks[0].setKind(tok::annot_pragma_opencl_extension);
1452*67e74705SXin Li Toks[0].setLocation(NameLoc);
1453*67e74705SXin Li Toks[0].setAnnotationValue(data.getOpaqueValue());
1454*67e74705SXin Li Toks[0].setAnnotationEndLoc(StateLoc);
1455*67e74705SXin Li PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
1456*67e74705SXin Li
1457*67e74705SXin Li if (PP.getPPCallbacks())
1458*67e74705SXin Li PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename,
1459*67e74705SXin Li StateLoc, state);
1460*67e74705SXin Li }
1461*67e74705SXin Li
1462*67e74705SXin Li /// \brief Handle '#pragma omp ...' when OpenMP is disabled.
1463*67e74705SXin Li ///
1464*67e74705SXin Li void
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & FirstTok)1465*67e74705SXin Li PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
1466*67e74705SXin Li PragmaIntroducerKind Introducer,
1467*67e74705SXin Li Token &FirstTok) {
1468*67e74705SXin Li if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
1469*67e74705SXin Li FirstTok.getLocation())) {
1470*67e74705SXin Li PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
1471*67e74705SXin Li PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
1472*67e74705SXin Li diag::Severity::Ignored, SourceLocation());
1473*67e74705SXin Li }
1474*67e74705SXin Li PP.DiscardUntilEndOfDirective();
1475*67e74705SXin Li }
1476*67e74705SXin Li
1477*67e74705SXin Li /// \brief Handle '#pragma omp ...' when OpenMP is enabled.
1478*67e74705SXin Li ///
1479*67e74705SXin Li void
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & FirstTok)1480*67e74705SXin Li PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
1481*67e74705SXin Li PragmaIntroducerKind Introducer,
1482*67e74705SXin Li Token &FirstTok) {
1483*67e74705SXin Li SmallVector<Token, 16> Pragma;
1484*67e74705SXin Li Token Tok;
1485*67e74705SXin Li Tok.startToken();
1486*67e74705SXin Li Tok.setKind(tok::annot_pragma_openmp);
1487*67e74705SXin Li Tok.setLocation(FirstTok.getLocation());
1488*67e74705SXin Li
1489*67e74705SXin Li while (Tok.isNot(tok::eod)) {
1490*67e74705SXin Li Pragma.push_back(Tok);
1491*67e74705SXin Li PP.Lex(Tok);
1492*67e74705SXin Li }
1493*67e74705SXin Li SourceLocation EodLoc = Tok.getLocation();
1494*67e74705SXin Li Tok.startToken();
1495*67e74705SXin Li Tok.setKind(tok::annot_pragma_openmp_end);
1496*67e74705SXin Li Tok.setLocation(EodLoc);
1497*67e74705SXin Li Pragma.push_back(Tok);
1498*67e74705SXin Li
1499*67e74705SXin Li auto Toks = llvm::make_unique<Token[]>(Pragma.size());
1500*67e74705SXin Li std::copy(Pragma.begin(), Pragma.end(), Toks.get());
1501*67e74705SXin Li PP.EnterTokenStream(std::move(Toks), Pragma.size(),
1502*67e74705SXin Li /*DisableMacroExpansion=*/false);
1503*67e74705SXin Li }
1504*67e74705SXin Li
1505*67e74705SXin Li /// \brief Handle '#pragma pointers_to_members'
1506*67e74705SXin Li // The grammar for this pragma is as follows:
1507*67e74705SXin Li //
1508*67e74705SXin Li // <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
1509*67e74705SXin Li //
1510*67e74705SXin Li // #pragma pointers_to_members '(' 'best_case' ')'
1511*67e74705SXin Li // #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
1512*67e74705SXin Li // #pragma pointers_to_members '(' inheritance-model ')'
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1513*67e74705SXin Li void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
1514*67e74705SXin Li PragmaIntroducerKind Introducer,
1515*67e74705SXin Li Token &Tok) {
1516*67e74705SXin Li SourceLocation PointersToMembersLoc = Tok.getLocation();
1517*67e74705SXin Li PP.Lex(Tok);
1518*67e74705SXin Li if (Tok.isNot(tok::l_paren)) {
1519*67e74705SXin Li PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
1520*67e74705SXin Li << "pointers_to_members";
1521*67e74705SXin Li return;
1522*67e74705SXin Li }
1523*67e74705SXin Li PP.Lex(Tok);
1524*67e74705SXin Li const IdentifierInfo *Arg = Tok.getIdentifierInfo();
1525*67e74705SXin Li if (!Arg) {
1526*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1527*67e74705SXin Li << "pointers_to_members";
1528*67e74705SXin Li return;
1529*67e74705SXin Li }
1530*67e74705SXin Li PP.Lex(Tok);
1531*67e74705SXin Li
1532*67e74705SXin Li LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
1533*67e74705SXin Li if (Arg->isStr("best_case")) {
1534*67e74705SXin Li RepresentationMethod = LangOptions::PPTMK_BestCase;
1535*67e74705SXin Li } else {
1536*67e74705SXin Li if (Arg->isStr("full_generality")) {
1537*67e74705SXin Li if (Tok.is(tok::comma)) {
1538*67e74705SXin Li PP.Lex(Tok);
1539*67e74705SXin Li
1540*67e74705SXin Li Arg = Tok.getIdentifierInfo();
1541*67e74705SXin Li if (!Arg) {
1542*67e74705SXin Li PP.Diag(Tok.getLocation(),
1543*67e74705SXin Li diag::err_pragma_pointers_to_members_unknown_kind)
1544*67e74705SXin Li << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
1545*67e74705SXin Li return;
1546*67e74705SXin Li }
1547*67e74705SXin Li PP.Lex(Tok);
1548*67e74705SXin Li } else if (Tok.is(tok::r_paren)) {
1549*67e74705SXin Li // #pragma pointers_to_members(full_generality) implicitly specifies
1550*67e74705SXin Li // virtual_inheritance.
1551*67e74705SXin Li Arg = nullptr;
1552*67e74705SXin Li RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
1553*67e74705SXin Li } else {
1554*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::err_expected_punc)
1555*67e74705SXin Li << "full_generality";
1556*67e74705SXin Li return;
1557*67e74705SXin Li }
1558*67e74705SXin Li }
1559*67e74705SXin Li
1560*67e74705SXin Li if (Arg) {
1561*67e74705SXin Li if (Arg->isStr("single_inheritance")) {
1562*67e74705SXin Li RepresentationMethod =
1563*67e74705SXin Li LangOptions::PPTMK_FullGeneralitySingleInheritance;
1564*67e74705SXin Li } else if (Arg->isStr("multiple_inheritance")) {
1565*67e74705SXin Li RepresentationMethod =
1566*67e74705SXin Li LangOptions::PPTMK_FullGeneralityMultipleInheritance;
1567*67e74705SXin Li } else if (Arg->isStr("virtual_inheritance")) {
1568*67e74705SXin Li RepresentationMethod =
1569*67e74705SXin Li LangOptions::PPTMK_FullGeneralityVirtualInheritance;
1570*67e74705SXin Li } else {
1571*67e74705SXin Li PP.Diag(Tok.getLocation(),
1572*67e74705SXin Li diag::err_pragma_pointers_to_members_unknown_kind)
1573*67e74705SXin Li << Arg << /*HasPointerDeclaration*/ 1;
1574*67e74705SXin Li return;
1575*67e74705SXin Li }
1576*67e74705SXin Li }
1577*67e74705SXin Li }
1578*67e74705SXin Li
1579*67e74705SXin Li if (Tok.isNot(tok::r_paren)) {
1580*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
1581*67e74705SXin Li << (Arg ? Arg->getName() : "full_generality");
1582*67e74705SXin Li return;
1583*67e74705SXin Li }
1584*67e74705SXin Li
1585*67e74705SXin Li SourceLocation EndLoc = Tok.getLocation();
1586*67e74705SXin Li PP.Lex(Tok);
1587*67e74705SXin Li if (Tok.isNot(tok::eod)) {
1588*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1589*67e74705SXin Li << "pointers_to_members";
1590*67e74705SXin Li return;
1591*67e74705SXin Li }
1592*67e74705SXin Li
1593*67e74705SXin Li Token AnnotTok;
1594*67e74705SXin Li AnnotTok.startToken();
1595*67e74705SXin Li AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
1596*67e74705SXin Li AnnotTok.setLocation(PointersToMembersLoc);
1597*67e74705SXin Li AnnotTok.setAnnotationEndLoc(EndLoc);
1598*67e74705SXin Li AnnotTok.setAnnotationValue(
1599*67e74705SXin Li reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
1600*67e74705SXin Li PP.EnterToken(AnnotTok);
1601*67e74705SXin Li }
1602*67e74705SXin Li
1603*67e74705SXin Li /// \brief Handle '#pragma vtordisp'
1604*67e74705SXin Li // The grammar for this pragma is as follows:
1605*67e74705SXin Li //
1606*67e74705SXin Li // <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
1607*67e74705SXin Li //
1608*67e74705SXin Li // #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
1609*67e74705SXin Li // #pragma vtordisp '(' 'pop' ')'
1610*67e74705SXin Li // #pragma vtordisp '(' ')'
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1611*67e74705SXin Li void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
1612*67e74705SXin Li PragmaIntroducerKind Introducer,
1613*67e74705SXin Li Token &Tok) {
1614*67e74705SXin Li SourceLocation VtorDispLoc = Tok.getLocation();
1615*67e74705SXin Li PP.Lex(Tok);
1616*67e74705SXin Li if (Tok.isNot(tok::l_paren)) {
1617*67e74705SXin Li PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
1618*67e74705SXin Li return;
1619*67e74705SXin Li }
1620*67e74705SXin Li PP.Lex(Tok);
1621*67e74705SXin Li
1622*67e74705SXin Li Sema::PragmaMsStackAction Action = Sema::PSK_Set;
1623*67e74705SXin Li const IdentifierInfo *II = Tok.getIdentifierInfo();
1624*67e74705SXin Li if (II) {
1625*67e74705SXin Li if (II->isStr("push")) {
1626*67e74705SXin Li // #pragma vtordisp(push, mode)
1627*67e74705SXin Li PP.Lex(Tok);
1628*67e74705SXin Li if (Tok.isNot(tok::comma)) {
1629*67e74705SXin Li PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
1630*67e74705SXin Li return;
1631*67e74705SXin Li }
1632*67e74705SXin Li PP.Lex(Tok);
1633*67e74705SXin Li Action = Sema::PSK_Push_Set;
1634*67e74705SXin Li // not push, could be on/off
1635*67e74705SXin Li } else if (II->isStr("pop")) {
1636*67e74705SXin Li // #pragma vtordisp(pop)
1637*67e74705SXin Li PP.Lex(Tok);
1638*67e74705SXin Li Action = Sema::PSK_Pop;
1639*67e74705SXin Li }
1640*67e74705SXin Li // not push or pop, could be on/off
1641*67e74705SXin Li } else {
1642*67e74705SXin Li if (Tok.is(tok::r_paren)) {
1643*67e74705SXin Li // #pragma vtordisp()
1644*67e74705SXin Li Action = Sema::PSK_Reset;
1645*67e74705SXin Li }
1646*67e74705SXin Li }
1647*67e74705SXin Li
1648*67e74705SXin Li
1649*67e74705SXin Li uint64_t Value = 0;
1650*67e74705SXin Li if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
1651*67e74705SXin Li const IdentifierInfo *II = Tok.getIdentifierInfo();
1652*67e74705SXin Li if (II && II->isStr("off")) {
1653*67e74705SXin Li PP.Lex(Tok);
1654*67e74705SXin Li Value = 0;
1655*67e74705SXin Li } else if (II && II->isStr("on")) {
1656*67e74705SXin Li PP.Lex(Tok);
1657*67e74705SXin Li Value = 1;
1658*67e74705SXin Li } else if (Tok.is(tok::numeric_constant) &&
1659*67e74705SXin Li PP.parseSimpleIntegerLiteral(Tok, Value)) {
1660*67e74705SXin Li if (Value > 2) {
1661*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
1662*67e74705SXin Li << 0 << 2 << "vtordisp";
1663*67e74705SXin Li return;
1664*67e74705SXin Li }
1665*67e74705SXin Li } else {
1666*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
1667*67e74705SXin Li << "vtordisp";
1668*67e74705SXin Li return;
1669*67e74705SXin Li }
1670*67e74705SXin Li }
1671*67e74705SXin Li
1672*67e74705SXin Li // Finish the pragma: ')' $
1673*67e74705SXin Li if (Tok.isNot(tok::r_paren)) {
1674*67e74705SXin Li PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
1675*67e74705SXin Li return;
1676*67e74705SXin Li }
1677*67e74705SXin Li SourceLocation EndLoc = Tok.getLocation();
1678*67e74705SXin Li PP.Lex(Tok);
1679*67e74705SXin Li if (Tok.isNot(tok::eod)) {
1680*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1681*67e74705SXin Li << "vtordisp";
1682*67e74705SXin Li return;
1683*67e74705SXin Li }
1684*67e74705SXin Li
1685*67e74705SXin Li // Enter the annotation.
1686*67e74705SXin Li Token AnnotTok;
1687*67e74705SXin Li AnnotTok.startToken();
1688*67e74705SXin Li AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
1689*67e74705SXin Li AnnotTok.setLocation(VtorDispLoc);
1690*67e74705SXin Li AnnotTok.setAnnotationEndLoc(EndLoc);
1691*67e74705SXin Li AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
1692*67e74705SXin Li static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
1693*67e74705SXin Li PP.EnterToken(AnnotTok);
1694*67e74705SXin Li }
1695*67e74705SXin Li
1696*67e74705SXin Li /// \brief Handle all MS pragmas. Simply forwards the tokens after inserting
1697*67e74705SXin Li /// an annotation token.
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1698*67e74705SXin Li void PragmaMSPragma::HandlePragma(Preprocessor &PP,
1699*67e74705SXin Li PragmaIntroducerKind Introducer,
1700*67e74705SXin Li Token &Tok) {
1701*67e74705SXin Li Token EoF, AnnotTok;
1702*67e74705SXin Li EoF.startToken();
1703*67e74705SXin Li EoF.setKind(tok::eof);
1704*67e74705SXin Li AnnotTok.startToken();
1705*67e74705SXin Li AnnotTok.setKind(tok::annot_pragma_ms_pragma);
1706*67e74705SXin Li AnnotTok.setLocation(Tok.getLocation());
1707*67e74705SXin Li AnnotTok.setAnnotationEndLoc(Tok.getLocation());
1708*67e74705SXin Li SmallVector<Token, 8> TokenVector;
1709*67e74705SXin Li // Suck up all of the tokens before the eod.
1710*67e74705SXin Li for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
1711*67e74705SXin Li TokenVector.push_back(Tok);
1712*67e74705SXin Li AnnotTok.setAnnotationEndLoc(Tok.getLocation());
1713*67e74705SXin Li }
1714*67e74705SXin Li // Add a sentinal EoF token to the end of the list.
1715*67e74705SXin Li TokenVector.push_back(EoF);
1716*67e74705SXin Li // We must allocate this array with new because EnterTokenStream is going to
1717*67e74705SXin Li // delete it later.
1718*67e74705SXin Li auto TokenArray = llvm::make_unique<Token[]>(TokenVector.size());
1719*67e74705SXin Li std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
1720*67e74705SXin Li auto Value = new (PP.getPreprocessorAllocator())
1721*67e74705SXin Li std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
1722*67e74705SXin Li TokenVector.size());
1723*67e74705SXin Li AnnotTok.setAnnotationValue(Value);
1724*67e74705SXin Li PP.EnterToken(AnnotTok);
1725*67e74705SXin Li }
1726*67e74705SXin Li
1727*67e74705SXin Li /// \brief Handle the Microsoft \#pragma detect_mismatch extension.
1728*67e74705SXin Li ///
1729*67e74705SXin Li /// The syntax is:
1730*67e74705SXin Li /// \code
1731*67e74705SXin Li /// #pragma detect_mismatch("name", "value")
1732*67e74705SXin Li /// \endcode
1733*67e74705SXin Li /// Where 'name' and 'value' are quoted strings. The values are embedded in
1734*67e74705SXin Li /// the object file and passed along to the linker. If the linker detects a
1735*67e74705SXin Li /// mismatch in the object file's values for the given name, a LNK2038 error
1736*67e74705SXin Li /// is emitted. See MSDN for more details.
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1737*67e74705SXin Li void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
1738*67e74705SXin Li PragmaIntroducerKind Introducer,
1739*67e74705SXin Li Token &Tok) {
1740*67e74705SXin Li SourceLocation DetectMismatchLoc = Tok.getLocation();
1741*67e74705SXin Li PP.Lex(Tok);
1742*67e74705SXin Li if (Tok.isNot(tok::l_paren)) {
1743*67e74705SXin Li PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
1744*67e74705SXin Li return;
1745*67e74705SXin Li }
1746*67e74705SXin Li
1747*67e74705SXin Li // Read the name to embed, which must be a string literal.
1748*67e74705SXin Li std::string NameString;
1749*67e74705SXin Li if (!PP.LexStringLiteral(Tok, NameString,
1750*67e74705SXin Li "pragma detect_mismatch",
1751*67e74705SXin Li /*MacroExpansion=*/true))
1752*67e74705SXin Li return;
1753*67e74705SXin Li
1754*67e74705SXin Li // Read the comma followed by a second string literal.
1755*67e74705SXin Li std::string ValueString;
1756*67e74705SXin Li if (Tok.isNot(tok::comma)) {
1757*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1758*67e74705SXin Li return;
1759*67e74705SXin Li }
1760*67e74705SXin Li
1761*67e74705SXin Li if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
1762*67e74705SXin Li /*MacroExpansion=*/true))
1763*67e74705SXin Li return;
1764*67e74705SXin Li
1765*67e74705SXin Li if (Tok.isNot(tok::r_paren)) {
1766*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
1767*67e74705SXin Li return;
1768*67e74705SXin Li }
1769*67e74705SXin Li PP.Lex(Tok); // Eat the r_paren.
1770*67e74705SXin Li
1771*67e74705SXin Li if (Tok.isNot(tok::eod)) {
1772*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1773*67e74705SXin Li return;
1774*67e74705SXin Li }
1775*67e74705SXin Li
1776*67e74705SXin Li // If the pragma is lexically sound, notify any interested PPCallbacks.
1777*67e74705SXin Li if (PP.getPPCallbacks())
1778*67e74705SXin Li PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
1779*67e74705SXin Li ValueString);
1780*67e74705SXin Li
1781*67e74705SXin Li Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
1782*67e74705SXin Li }
1783*67e74705SXin Li
1784*67e74705SXin Li /// \brief Handle the microsoft \#pragma comment extension.
1785*67e74705SXin Li ///
1786*67e74705SXin Li /// The syntax is:
1787*67e74705SXin Li /// \code
1788*67e74705SXin Li /// #pragma comment(linker, "foo")
1789*67e74705SXin Li /// \endcode
1790*67e74705SXin Li /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
1791*67e74705SXin Li /// "foo" is a string, which is fully macro expanded, and permits string
1792*67e74705SXin Li /// concatenation, embedded escape characters etc. See MSDN for more details.
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1793*67e74705SXin Li void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
1794*67e74705SXin Li PragmaIntroducerKind Introducer,
1795*67e74705SXin Li Token &Tok) {
1796*67e74705SXin Li SourceLocation CommentLoc = Tok.getLocation();
1797*67e74705SXin Li PP.Lex(Tok);
1798*67e74705SXin Li if (Tok.isNot(tok::l_paren)) {
1799*67e74705SXin Li PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1800*67e74705SXin Li return;
1801*67e74705SXin Li }
1802*67e74705SXin Li
1803*67e74705SXin Li // Read the identifier.
1804*67e74705SXin Li PP.Lex(Tok);
1805*67e74705SXin Li if (Tok.isNot(tok::identifier)) {
1806*67e74705SXin Li PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1807*67e74705SXin Li return;
1808*67e74705SXin Li }
1809*67e74705SXin Li
1810*67e74705SXin Li // Verify that this is one of the 5 whitelisted options.
1811*67e74705SXin Li IdentifierInfo *II = Tok.getIdentifierInfo();
1812*67e74705SXin Li PragmaMSCommentKind Kind =
1813*67e74705SXin Li llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
1814*67e74705SXin Li .Case("linker", PCK_Linker)
1815*67e74705SXin Li .Case("lib", PCK_Lib)
1816*67e74705SXin Li .Case("compiler", PCK_Compiler)
1817*67e74705SXin Li .Case("exestr", PCK_ExeStr)
1818*67e74705SXin Li .Case("user", PCK_User)
1819*67e74705SXin Li .Default(PCK_Unknown);
1820*67e74705SXin Li if (Kind == PCK_Unknown) {
1821*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
1822*67e74705SXin Li return;
1823*67e74705SXin Li }
1824*67e74705SXin Li
1825*67e74705SXin Li // On PS4, issue a warning about any pragma comments other than
1826*67e74705SXin Li // #pragma comment lib.
1827*67e74705SXin Li if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) {
1828*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
1829*67e74705SXin Li << II->getName();
1830*67e74705SXin Li return;
1831*67e74705SXin Li }
1832*67e74705SXin Li
1833*67e74705SXin Li // Read the optional string if present.
1834*67e74705SXin Li PP.Lex(Tok);
1835*67e74705SXin Li std::string ArgumentString;
1836*67e74705SXin Li if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
1837*67e74705SXin Li "pragma comment",
1838*67e74705SXin Li /*MacroExpansion=*/true))
1839*67e74705SXin Li return;
1840*67e74705SXin Li
1841*67e74705SXin Li // FIXME: warn that 'exestr' is deprecated.
1842*67e74705SXin Li // FIXME: If the kind is "compiler" warn if the string is present (it is
1843*67e74705SXin Li // ignored).
1844*67e74705SXin Li // The MSDN docs say that "lib" and "linker" require a string and have a short
1845*67e74705SXin Li // whitelist of linker options they support, but in practice MSVC doesn't
1846*67e74705SXin Li // issue a diagnostic. Therefore neither does clang.
1847*67e74705SXin Li
1848*67e74705SXin Li if (Tok.isNot(tok::r_paren)) {
1849*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1850*67e74705SXin Li return;
1851*67e74705SXin Li }
1852*67e74705SXin Li PP.Lex(Tok); // eat the r_paren.
1853*67e74705SXin Li
1854*67e74705SXin Li if (Tok.isNot(tok::eod)) {
1855*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1856*67e74705SXin Li return;
1857*67e74705SXin Li }
1858*67e74705SXin Li
1859*67e74705SXin Li // If the pragma is lexically sound, notify any interested PPCallbacks.
1860*67e74705SXin Li if (PP.getPPCallbacks())
1861*67e74705SXin Li PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
1862*67e74705SXin Li
1863*67e74705SXin Li Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
1864*67e74705SXin Li }
1865*67e74705SXin Li
1866*67e74705SXin Li // #pragma clang optimize off
1867*67e74705SXin Li // #pragma clang optimize on
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & FirstToken)1868*67e74705SXin Li void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
1869*67e74705SXin Li PragmaIntroducerKind Introducer,
1870*67e74705SXin Li Token &FirstToken) {
1871*67e74705SXin Li Token Tok;
1872*67e74705SXin Li PP.Lex(Tok);
1873*67e74705SXin Li if (Tok.is(tok::eod)) {
1874*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
1875*67e74705SXin Li << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
1876*67e74705SXin Li return;
1877*67e74705SXin Li }
1878*67e74705SXin Li if (Tok.isNot(tok::identifier)) {
1879*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1880*67e74705SXin Li << PP.getSpelling(Tok);
1881*67e74705SXin Li return;
1882*67e74705SXin Li }
1883*67e74705SXin Li const IdentifierInfo *II = Tok.getIdentifierInfo();
1884*67e74705SXin Li // The only accepted values are 'on' or 'off'.
1885*67e74705SXin Li bool IsOn = false;
1886*67e74705SXin Li if (II->isStr("on")) {
1887*67e74705SXin Li IsOn = true;
1888*67e74705SXin Li } else if (!II->isStr("off")) {
1889*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1890*67e74705SXin Li << PP.getSpelling(Tok);
1891*67e74705SXin Li return;
1892*67e74705SXin Li }
1893*67e74705SXin Li PP.Lex(Tok);
1894*67e74705SXin Li
1895*67e74705SXin Li if (Tok.isNot(tok::eod)) {
1896*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
1897*67e74705SXin Li << PP.getSpelling(Tok);
1898*67e74705SXin Li return;
1899*67e74705SXin Li }
1900*67e74705SXin Li
1901*67e74705SXin Li Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
1902*67e74705SXin Li }
1903*67e74705SXin Li
1904*67e74705SXin Li /// \brief Parses loop or unroll pragma hint value and fills in Info.
ParseLoopHintValue(Preprocessor & PP,Token & Tok,Token PragmaName,Token Option,bool ValueInParens,PragmaLoopHintInfo & Info)1905*67e74705SXin Li static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
1906*67e74705SXin Li Token Option, bool ValueInParens,
1907*67e74705SXin Li PragmaLoopHintInfo &Info) {
1908*67e74705SXin Li SmallVector<Token, 1> ValueList;
1909*67e74705SXin Li int OpenParens = ValueInParens ? 1 : 0;
1910*67e74705SXin Li // Read constant expression.
1911*67e74705SXin Li while (Tok.isNot(tok::eod)) {
1912*67e74705SXin Li if (Tok.is(tok::l_paren))
1913*67e74705SXin Li OpenParens++;
1914*67e74705SXin Li else if (Tok.is(tok::r_paren)) {
1915*67e74705SXin Li OpenParens--;
1916*67e74705SXin Li if (OpenParens == 0 && ValueInParens)
1917*67e74705SXin Li break;
1918*67e74705SXin Li }
1919*67e74705SXin Li
1920*67e74705SXin Li ValueList.push_back(Tok);
1921*67e74705SXin Li PP.Lex(Tok);
1922*67e74705SXin Li }
1923*67e74705SXin Li
1924*67e74705SXin Li if (ValueInParens) {
1925*67e74705SXin Li // Read ')'
1926*67e74705SXin Li if (Tok.isNot(tok::r_paren)) {
1927*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
1928*67e74705SXin Li return true;
1929*67e74705SXin Li }
1930*67e74705SXin Li PP.Lex(Tok);
1931*67e74705SXin Li }
1932*67e74705SXin Li
1933*67e74705SXin Li Token EOFTok;
1934*67e74705SXin Li EOFTok.startToken();
1935*67e74705SXin Li EOFTok.setKind(tok::eof);
1936*67e74705SXin Li EOFTok.setLocation(Tok.getLocation());
1937*67e74705SXin Li ValueList.push_back(EOFTok); // Terminates expression for parsing.
1938*67e74705SXin Li
1939*67e74705SXin Li Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
1940*67e74705SXin Li
1941*67e74705SXin Li Info.PragmaName = PragmaName;
1942*67e74705SXin Li Info.Option = Option;
1943*67e74705SXin Li return false;
1944*67e74705SXin Li }
1945*67e74705SXin Li
1946*67e74705SXin Li /// \brief Handle the \#pragma clang loop directive.
1947*67e74705SXin Li /// #pragma clang 'loop' loop-hints
1948*67e74705SXin Li ///
1949*67e74705SXin Li /// loop-hints:
1950*67e74705SXin Li /// loop-hint loop-hints[opt]
1951*67e74705SXin Li ///
1952*67e74705SXin Li /// loop-hint:
1953*67e74705SXin Li /// 'vectorize' '(' loop-hint-keyword ')'
1954*67e74705SXin Li /// 'interleave' '(' loop-hint-keyword ')'
1955*67e74705SXin Li /// 'unroll' '(' unroll-hint-keyword ')'
1956*67e74705SXin Li /// 'vectorize_width' '(' loop-hint-value ')'
1957*67e74705SXin Li /// 'interleave_count' '(' loop-hint-value ')'
1958*67e74705SXin Li /// 'unroll_count' '(' loop-hint-value ')'
1959*67e74705SXin Li ///
1960*67e74705SXin Li /// loop-hint-keyword:
1961*67e74705SXin Li /// 'enable'
1962*67e74705SXin Li /// 'disable'
1963*67e74705SXin Li /// 'assume_safety'
1964*67e74705SXin Li ///
1965*67e74705SXin Li /// unroll-hint-keyword:
1966*67e74705SXin Li /// 'enable'
1967*67e74705SXin Li /// 'disable'
1968*67e74705SXin Li /// 'full'
1969*67e74705SXin Li ///
1970*67e74705SXin Li /// loop-hint-value:
1971*67e74705SXin Li /// constant-expression
1972*67e74705SXin Li ///
1973*67e74705SXin Li /// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
1974*67e74705SXin Li /// try vectorizing the instructions of the loop it precedes. Specifying
1975*67e74705SXin Li /// interleave(enable) or interleave_count(_value_) instructs llvm to try
1976*67e74705SXin Li /// interleaving multiple iterations of the loop it precedes. The width of the
1977*67e74705SXin Li /// vector instructions is specified by vectorize_width() and the number of
1978*67e74705SXin Li /// interleaved loop iterations is specified by interleave_count(). Specifying a
1979*67e74705SXin Li /// value of 1 effectively disables vectorization/interleaving, even if it is
1980*67e74705SXin Li /// possible and profitable, and 0 is invalid. The loop vectorizer currently
1981*67e74705SXin Li /// only works on inner loops.
1982*67e74705SXin Li ///
1983*67e74705SXin Li /// The unroll and unroll_count directives control the concatenation
1984*67e74705SXin Li /// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
1985*67e74705SXin Li /// completely if the trip count is known at compile time and unroll partially
1986*67e74705SXin Li /// if the trip count is not known. Specifying unroll(full) is similar to
1987*67e74705SXin Li /// unroll(enable) but will unroll the loop only if the trip count is known at
1988*67e74705SXin Li /// compile time. Specifying unroll(disable) disables unrolling for the
1989*67e74705SXin Li /// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
1990*67e74705SXin Li /// loop the number of times indicated by the value.
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1991*67e74705SXin Li void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
1992*67e74705SXin Li PragmaIntroducerKind Introducer,
1993*67e74705SXin Li Token &Tok) {
1994*67e74705SXin Li // Incoming token is "loop" from "#pragma clang loop".
1995*67e74705SXin Li Token PragmaName = Tok;
1996*67e74705SXin Li SmallVector<Token, 1> TokenList;
1997*67e74705SXin Li
1998*67e74705SXin Li // Lex the optimization option and verify it is an identifier.
1999*67e74705SXin Li PP.Lex(Tok);
2000*67e74705SXin Li if (Tok.isNot(tok::identifier)) {
2001*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2002*67e74705SXin Li << /*MissingOption=*/true << "";
2003*67e74705SXin Li return;
2004*67e74705SXin Li }
2005*67e74705SXin Li
2006*67e74705SXin Li while (Tok.is(tok::identifier)) {
2007*67e74705SXin Li Token Option = Tok;
2008*67e74705SXin Li IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2009*67e74705SXin Li
2010*67e74705SXin Li bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
2011*67e74705SXin Li .Case("vectorize", true)
2012*67e74705SXin Li .Case("interleave", true)
2013*67e74705SXin Li .Case("unroll", true)
2014*67e74705SXin Li .Case("distribute", true)
2015*67e74705SXin Li .Case("vectorize_width", true)
2016*67e74705SXin Li .Case("interleave_count", true)
2017*67e74705SXin Li .Case("unroll_count", true)
2018*67e74705SXin Li .Default(false);
2019*67e74705SXin Li if (!OptionValid) {
2020*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2021*67e74705SXin Li << /*MissingOption=*/false << OptionInfo;
2022*67e74705SXin Li return;
2023*67e74705SXin Li }
2024*67e74705SXin Li PP.Lex(Tok);
2025*67e74705SXin Li
2026*67e74705SXin Li // Read '('
2027*67e74705SXin Li if (Tok.isNot(tok::l_paren)) {
2028*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
2029*67e74705SXin Li return;
2030*67e74705SXin Li }
2031*67e74705SXin Li PP.Lex(Tok);
2032*67e74705SXin Li
2033*67e74705SXin Li auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2034*67e74705SXin Li if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
2035*67e74705SXin Li *Info))
2036*67e74705SXin Li return;
2037*67e74705SXin Li
2038*67e74705SXin Li // Generate the loop hint token.
2039*67e74705SXin Li Token LoopHintTok;
2040*67e74705SXin Li LoopHintTok.startToken();
2041*67e74705SXin Li LoopHintTok.setKind(tok::annot_pragma_loop_hint);
2042*67e74705SXin Li LoopHintTok.setLocation(PragmaName.getLocation());
2043*67e74705SXin Li LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
2044*67e74705SXin Li LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
2045*67e74705SXin Li TokenList.push_back(LoopHintTok);
2046*67e74705SXin Li }
2047*67e74705SXin Li
2048*67e74705SXin Li if (Tok.isNot(tok::eod)) {
2049*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2050*67e74705SXin Li << "clang loop";
2051*67e74705SXin Li return;
2052*67e74705SXin Li }
2053*67e74705SXin Li
2054*67e74705SXin Li auto TokenArray = llvm::make_unique<Token[]>(TokenList.size());
2055*67e74705SXin Li std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
2056*67e74705SXin Li
2057*67e74705SXin Li PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
2058*67e74705SXin Li /*DisableMacroExpansion=*/false);
2059*67e74705SXin Li }
2060*67e74705SXin Li
2061*67e74705SXin Li /// \brief Handle the loop unroll optimization pragmas.
2062*67e74705SXin Li /// #pragma unroll
2063*67e74705SXin Li /// #pragma unroll unroll-hint-value
2064*67e74705SXin Li /// #pragma unroll '(' unroll-hint-value ')'
2065*67e74705SXin Li /// #pragma nounroll
2066*67e74705SXin Li ///
2067*67e74705SXin Li /// unroll-hint-value:
2068*67e74705SXin Li /// constant-expression
2069*67e74705SXin Li ///
2070*67e74705SXin Li /// Loop unrolling hints can be specified with '#pragma unroll' or
2071*67e74705SXin Li /// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
2072*67e74705SXin Li /// contained in parentheses. With no argument the directive instructs llvm to
2073*67e74705SXin Li /// try to unroll the loop completely. A positive integer argument can be
2074*67e74705SXin Li /// specified to indicate the number of times the loop should be unrolled. To
2075*67e74705SXin Li /// maximize compatibility with other compilers the unroll count argument can be
2076*67e74705SXin Li /// specified with or without parentheses. Specifying, '#pragma nounroll'
2077*67e74705SXin Li /// disables unrolling of the loop.
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)2078*67e74705SXin Li void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
2079*67e74705SXin Li PragmaIntroducerKind Introducer,
2080*67e74705SXin Li Token &Tok) {
2081*67e74705SXin Li // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
2082*67e74705SXin Li // "#pragma nounroll".
2083*67e74705SXin Li Token PragmaName = Tok;
2084*67e74705SXin Li PP.Lex(Tok);
2085*67e74705SXin Li auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2086*67e74705SXin Li if (Tok.is(tok::eod)) {
2087*67e74705SXin Li // nounroll or unroll pragma without an argument.
2088*67e74705SXin Li Info->PragmaName = PragmaName;
2089*67e74705SXin Li Info->Option.startToken();
2090*67e74705SXin Li } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") {
2091*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2092*67e74705SXin Li << "nounroll";
2093*67e74705SXin Li return;
2094*67e74705SXin Li } else {
2095*67e74705SXin Li // Unroll pragma with an argument: "#pragma unroll N" or
2096*67e74705SXin Li // "#pragma unroll(N)".
2097*67e74705SXin Li // Read '(' if it exists.
2098*67e74705SXin Li bool ValueInParens = Tok.is(tok::l_paren);
2099*67e74705SXin Li if (ValueInParens)
2100*67e74705SXin Li PP.Lex(Tok);
2101*67e74705SXin Li
2102*67e74705SXin Li Token Option;
2103*67e74705SXin Li Option.startToken();
2104*67e74705SXin Li if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
2105*67e74705SXin Li return;
2106*67e74705SXin Li
2107*67e74705SXin Li // In CUDA, the argument to '#pragma unroll' should not be contained in
2108*67e74705SXin Li // parentheses.
2109*67e74705SXin Li if (PP.getLangOpts().CUDA && ValueInParens)
2110*67e74705SXin Li PP.Diag(Info->Toks[0].getLocation(),
2111*67e74705SXin Li diag::warn_pragma_unroll_cuda_value_in_parens);
2112*67e74705SXin Li
2113*67e74705SXin Li if (Tok.isNot(tok::eod)) {
2114*67e74705SXin Li PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2115*67e74705SXin Li << "unroll";
2116*67e74705SXin Li return;
2117*67e74705SXin Li }
2118*67e74705SXin Li }
2119*67e74705SXin Li
2120*67e74705SXin Li // Generate the hint token.
2121*67e74705SXin Li auto TokenArray = llvm::make_unique<Token[]>(1);
2122*67e74705SXin Li TokenArray[0].startToken();
2123*67e74705SXin Li TokenArray[0].setKind(tok::annot_pragma_loop_hint);
2124*67e74705SXin Li TokenArray[0].setLocation(PragmaName.getLocation());
2125*67e74705SXin Li TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
2126*67e74705SXin Li TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
2127*67e74705SXin Li PP.EnterTokenStream(std::move(TokenArray), 1,
2128*67e74705SXin Li /*DisableMacroExpansion=*/false);
2129*67e74705SXin Li }
2130