Coverage Report

Created: 2021-01-23 06:44

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Parse/ParsePragma.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file implements the language specific #pragma handlers.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "clang/AST/ASTContext.h"
14
#include "clang/Basic/PragmaKinds.h"
15
#include "clang/Basic/TargetInfo.h"
16
#include "clang/Lex/Preprocessor.h"
17
#include "clang/Parse/LoopHint.h"
18
#include "clang/Parse/ParseDiagnostic.h"
19
#include "clang/Parse/Parser.h"
20
#include "clang/Parse/RAIIObjectsForParser.h"
21
#include "clang/Sema/Scope.h"
22
#include "llvm/ADT/StringSwitch.h"
23
using namespace clang;
24
25
namespace {
26
27
struct PragmaAlignHandler : public PragmaHandler {
28
78.8k
  explicit PragmaAlignHandler() : PragmaHandler("align") {}
29
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
30
                    Token &FirstToken) override;
31
};
32
33
struct PragmaGCCVisibilityHandler : public PragmaHandler {
34
78.8k
  explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
35
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
36
                    Token &FirstToken) override;
37
};
38
39
struct PragmaOptionsHandler : public PragmaHandler {
40
78.8k
  explicit PragmaOptionsHandler() : PragmaHandler("options") {}
41
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
42
                    Token &FirstToken) override;
43
};
44
45
struct PragmaPackHandler : public PragmaHandler {
46
78.8k
  explicit PragmaPackHandler() : PragmaHandler("pack") {}
47
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
48
                    Token &FirstToken) override;
49
};
50
51
struct PragmaClangSectionHandler : public PragmaHandler {
52
  explicit PragmaClangSectionHandler(Sema &S)
53
78.8k
             : PragmaHandler("section"), Actions(S) {}
54
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
55
                    Token &FirstToken) override;
56
57
private:
58
  Sema &Actions;
59
};
60
61
struct PragmaMSStructHandler : public PragmaHandler {
62
78.8k
  explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
63
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
64
                    Token &FirstToken) override;
65
};
66
67
struct PragmaUnusedHandler : public PragmaHandler {
68
78.8k
  PragmaUnusedHandler() : PragmaHandler("unused") {}
69
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
70
                    Token &FirstToken) override;
71
};
72
73
struct PragmaWeakHandler : public PragmaHandler {
74
78.8k
  explicit PragmaWeakHandler() : PragmaHandler("weak") {}
75
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
76
                    Token &FirstToken) override;
77
};
78
79
struct PragmaRedefineExtnameHandler : public PragmaHandler {
80
78.8k
  explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
81
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
82
                    Token &FirstToken) override;
83
};
84
85
struct PragmaOpenCLExtensionHandler : public PragmaHandler {
86
595
  PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
87
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
88
                    Token &FirstToken) override;
89
};
90
91
92
struct PragmaFPContractHandler : public PragmaHandler {
93
78.8k
  PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
94
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
95
                    Token &FirstToken) override;
96
};
97
98
// Pragma STDC implementations.
99
100
/// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...".
101
struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
102
78.8k
  PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {}
103
104
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
105
27
                    Token &Tok) override {
106
27
    Token PragmaName = Tok;
107
27
    if (!PP.getTargetInfo().hasStrictFP() && 
!PP.getLangOpts().ExpStrictFP3
) {
108
3
      PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
109
3
          << PragmaName.getIdentifierInfo()->getName();
110
3
      return;
111
3
    }
112
24
    tok::OnOffSwitch OOS;
113
24
    if (PP.LexOnOffSwitch(OOS))
114
3
     return;
115
116
21
    MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
117
21
                                1);
118
21
    Toks[0].startToken();
119
21
    Toks[0].setKind(tok::annot_pragma_fenv_access);
120
21
    Toks[0].setLocation(Tok.getLocation());
121
21
    Toks[0].setAnnotationEndLoc(Tok.getLocation());
122
21
    Toks[0].setAnnotationValue(reinterpret_cast<void*>(
123
21
                               static_cast<uintptr_t>(OOS)));
124
21
    PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
125
21
                        /*IsReinject=*/false);
126
21
  }
127
};
128
129
/// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...".
130
struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
131
78.8k
  PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {}
132
133
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
134
9
                    Token &Tok) override {
135
9
    tok::OnOffSwitch OOS;
136
9
    PP.LexOnOffSwitch(OOS);
137
9
  }
138
};
139
140
/// Handler for "\#pragma STDC FENV_ROUND ...".
141
struct PragmaSTDC_FENV_ROUNDHandler : public PragmaHandler {
142
78.8k
  PragmaSTDC_FENV_ROUNDHandler() : PragmaHandler("FENV_ROUND") {}
143
144
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
145
                    Token &Tok) override;
146
};
147
148
/// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
149
struct PragmaSTDC_UnknownHandler : public PragmaHandler {
150
78.8k
  PragmaSTDC_UnknownHandler() = default;
151
152
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
153
2
                    Token &UnknownTok) override {
154
    // C99 6.10.6p2, unknown forms are not allowed.
155
2
    PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored);
156
2
  }
157
};
158
159
struct PragmaFPHandler : public PragmaHandler {
160
78.8k
  PragmaFPHandler() : PragmaHandler("fp") {}
161
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
162
                    Token &FirstToken) override;
163
};
164
165
struct PragmaNoOpenMPHandler : public PragmaHandler {
166
67.4k
  PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
167
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
168
                    Token &FirstToken) override;
169
};
170
171
struct PragmaOpenMPHandler : public PragmaHandler {
172
11.4k
  PragmaOpenMPHandler() : PragmaHandler("omp") { }
173
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
174
                    Token &FirstToken) override;
175
};
176
177
/// PragmaCommentHandler - "\#pragma comment ...".
178
struct PragmaCommentHandler : public PragmaHandler {
179
  PragmaCommentHandler(Sema &Actions)
180
34.8k
    : PragmaHandler("comment"), Actions(Actions) {}
181
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
182
                    Token &FirstToken) override;
183
184
private:
185
  Sema &Actions;
186
};
187
188
struct PragmaDetectMismatchHandler : public PragmaHandler {
189
  PragmaDetectMismatchHandler(Sema &Actions)
190
10.4k
    : PragmaHandler("detect_mismatch"), Actions(Actions) {}
191
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
192
                    Token &FirstToken) override;
193
194
private:
195
  Sema &Actions;
196
};
197
198
struct PragmaFloatControlHandler : public PragmaHandler {
199
  PragmaFloatControlHandler(Sema &Actions)
200
78.8k
      : PragmaHandler("float_control") {}
201
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
202
                    Token &FirstToken) override;
203
};
204
205
struct PragmaMSPointersToMembers : public PragmaHandler {
206
10.4k
  explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
207
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
208
                    Token &FirstToken) override;
209
};
210
211
struct PragmaMSVtorDisp : public PragmaHandler {
212
10.4k
  explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
213
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
214
                    Token &FirstToken) override;
215
};
216
217
struct PragmaMSPragma : public PragmaHandler {
218
62.4k
  explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
219
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
220
                    Token &FirstToken) override;
221
};
222
223
/// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
224
struct PragmaOptimizeHandler : public PragmaHandler {
225
  PragmaOptimizeHandler(Sema &S)
226
78.8k
    : PragmaHandler("optimize"), Actions(S) {}
227
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
228
                    Token &FirstToken) override;
229
230
private:
231
  Sema &Actions;
232
};
233
234
struct PragmaLoopHintHandler : public PragmaHandler {
235
78.8k
  PragmaLoopHintHandler() : PragmaHandler("loop") {}
236
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
237
                    Token &FirstToken) override;
238
};
239
240
struct PragmaUnrollHintHandler : public PragmaHandler {
241
315k
  PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
242
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
243
                    Token &FirstToken) override;
244
};
245
246
struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
247
10.4k
  PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
248
};
249
250
struct PragmaMSIntrinsicHandler : public PragmaHandler {
251
10.4k
  PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {}
252
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
253
                    Token &FirstToken) override;
254
};
255
256
struct PragmaMSOptimizeHandler : public PragmaHandler {
257
10.4k
  PragmaMSOptimizeHandler() : PragmaHandler("optimize") {}
258
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
259
                    Token &FirstToken) override;
260
};
261
262
struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
263
  PragmaForceCUDAHostDeviceHandler(Sema &Actions)
264
345
      : PragmaHandler("force_cuda_host_device"), Actions(Actions) {}
265
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
266
                    Token &FirstToken) override;
267
268
private:
269
  Sema &Actions;
270
};
271
272
/// PragmaAttributeHandler - "\#pragma clang attribute ...".
273
struct PragmaAttributeHandler : public PragmaHandler {
274
  PragmaAttributeHandler(AttributeFactory &AttrFactory)
275
78.8k
      : PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {}
276
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
277
                    Token &FirstToken) override;
278
279
  /// A pool of attributes that were parsed in \#pragma clang attribute.
280
  ParsedAttributes AttributesForPragmaAttribute;
281
};
282
283
struct PragmaMaxTokensHereHandler : public PragmaHandler {
284
78.8k
  PragmaMaxTokensHereHandler() : PragmaHandler("max_tokens_here") {}
285
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
286
                    Token &FirstToken) override;
287
};
288
289
struct PragmaMaxTokensTotalHandler : public PragmaHandler {
290
78.8k
  PragmaMaxTokensTotalHandler() : PragmaHandler("max_tokens_total") {}
291
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
292
                    Token &FirstToken) override;
293
};
294
295
}  // end namespace
296
297
78.8k
void Parser::initializePragmaHandlers() {
298
78.8k
  AlignHandler = std::make_unique<PragmaAlignHandler>();
299
78.8k
  PP.AddPragmaHandler(AlignHandler.get());
300
301
78.8k
  GCCVisibilityHandler = std::make_unique<PragmaGCCVisibilityHandler>();
302
78.8k
  PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
303
304
78.8k
  OptionsHandler = std::make_unique<PragmaOptionsHandler>();
305
78.8k
  PP.AddPragmaHandler(OptionsHandler.get());
306
307
78.8k
  PackHandler = std::make_unique<PragmaPackHandler>();
308
78.8k
  PP.AddPragmaHandler(PackHandler.get());
309
310
78.8k
  MSStructHandler = std::make_unique<PragmaMSStructHandler>();
311
78.8k
  PP.AddPragmaHandler(MSStructHandler.get());
312
313
78.8k
  UnusedHandler = std::make_unique<PragmaUnusedHandler>();
314
78.8k
  PP.AddPragmaHandler(UnusedHandler.get());
315
316
78.8k
  WeakHandler = std::make_unique<PragmaWeakHandler>();
317
78.8k
  PP.AddPragmaHandler(WeakHandler.get());
318
319
78.8k
  RedefineExtnameHandler = std::make_unique<PragmaRedefineExtnameHandler>();
320
78.8k
  PP.AddPragmaHandler(RedefineExtnameHandler.get());
321
322
78.8k
  FPContractHandler = std::make_unique<PragmaFPContractHandler>();
323
78.8k
  PP.AddPragmaHandler("STDC", FPContractHandler.get());
324
325
78.8k
  STDCFenvAccessHandler = std::make_unique<PragmaSTDC_FENV_ACCESSHandler>();
326
78.8k
  PP.AddPragmaHandler("STDC", STDCFenvAccessHandler.get());
327
328
78.8k
  STDCFenvRoundHandler = std::make_unique<PragmaSTDC_FENV_ROUNDHandler>();
329
78.8k
  PP.AddPragmaHandler("STDC", STDCFenvRoundHandler.get());
330
331
78.8k
  STDCCXLIMITHandler = std::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>();
332
78.8k
  PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get());
333
334
78.8k
  STDCUnknownHandler = std::make_unique<PragmaSTDC_UnknownHandler>();
335
78.8k
  PP.AddPragmaHandler("STDC", STDCUnknownHandler.get());
336
337
78.8k
  PCSectionHandler = std::make_unique<PragmaClangSectionHandler>(Actions);
338
78.8k
  PP.AddPragmaHandler("clang", PCSectionHandler.get());
339
340
78.8k
  if (getLangOpts().OpenCL) {
341
595
    OpenCLExtensionHandler = std::make_unique<PragmaOpenCLExtensionHandler>();
342
595
    PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
343
344
595
    PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
345
595
  }
346
78.8k
  if (getLangOpts().OpenMP)
347
11.4k
    OpenMPHandler = std::make_unique<PragmaOpenMPHandler>();
348
67.4k
  else
349
67.4k
    OpenMPHandler = std::make_unique<PragmaNoOpenMPHandler>();
350
78.8k
  PP.AddPragmaHandler(OpenMPHandler.get());
351
352
78.8k
  if (getLangOpts().MicrosoftExt ||
353
68.4k
      getTargetInfo().getTriple().isOSBinFormatELF()) {
354
34.8k
    MSCommentHandler = std::make_unique<PragmaCommentHandler>(Actions);
355
34.8k
    PP.AddPragmaHandler(MSCommentHandler.get());
356
34.8k
  }
357
358
78.8k
  FloatControlHandler = std::make_unique<PragmaFloatControlHandler>(Actions);
359
78.8k
  PP.AddPragmaHandler(FloatControlHandler.get());
360
78.8k
  if (getLangOpts().MicrosoftExt) {
361
10.4k
    MSDetectMismatchHandler =
362
10.4k
        std::make_unique<PragmaDetectMismatchHandler>(Actions);
363
10.4k
    PP.AddPragmaHandler(MSDetectMismatchHandler.get());
364
10.4k
    MSPointersToMembers = std::make_unique<PragmaMSPointersToMembers>();
365
10.4k
    PP.AddPragmaHandler(MSPointersToMembers.get());
366
10.4k
    MSVtorDisp = std::make_unique<PragmaMSVtorDisp>();
367
10.4k
    PP.AddPragmaHandler(MSVtorDisp.get());
368
10.4k
    MSInitSeg = std::make_unique<PragmaMSPragma>("init_seg");
369
10.4k
    PP.AddPragmaHandler(MSInitSeg.get());
370
10.4k
    MSDataSeg = std::make_unique<PragmaMSPragma>("data_seg");
371
10.4k
    PP.AddPragmaHandler(MSDataSeg.get());
372
10.4k
    MSBSSSeg = std::make_unique<PragmaMSPragma>("bss_seg");
373
10.4k
    PP.AddPragmaHandler(MSBSSSeg.get());
374
10.4k
    MSConstSeg = std::make_unique<PragmaMSPragma>("const_seg");
375
10.4k
    PP.AddPragmaHandler(MSConstSeg.get());
376
10.4k
    MSCodeSeg = std::make_unique<PragmaMSPragma>("code_seg");
377
10.4k
    PP.AddPragmaHandler(MSCodeSeg.get());
378
10.4k
    MSSection = std::make_unique<PragmaMSPragma>("section");
379
10.4k
    PP.AddPragmaHandler(MSSection.get());
380
10.4k
    MSRuntimeChecks = std::make_unique<PragmaMSRuntimeChecksHandler>();
381
10.4k
    PP.AddPragmaHandler(MSRuntimeChecks.get());
382
10.4k
    MSIntrinsic = std::make_unique<PragmaMSIntrinsicHandler>();
383
10.4k
    PP.AddPragmaHandler(MSIntrinsic.get());
384
10.4k
    MSOptimize = std::make_unique<PragmaMSOptimizeHandler>();
385
10.4k
    PP.AddPragmaHandler(MSOptimize.get());
386
10.4k
  }
387
388
78.8k
  if (getLangOpts().CUDA) {
389
345
    CUDAForceHostDeviceHandler =
390
345
        std::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions);
391
345
    PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
392
345
  }
393
394
78.8k
  OptimizeHandler = std::make_unique<PragmaOptimizeHandler>(Actions);
395
78.8k
  PP.AddPragmaHandler("clang", OptimizeHandler.get());
396
397
78.8k
  LoopHintHandler = std::make_unique<PragmaLoopHintHandler>();
398
78.8k
  PP.AddPragmaHandler("clang", LoopHintHandler.get());
399
400
78.8k
  UnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("unroll");
401
78.8k
  PP.AddPragmaHandler(UnrollHintHandler.get());
402
403
78.8k
  NoUnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("nounroll");
404
78.8k
  PP.AddPragmaHandler(NoUnrollHintHandler.get());
405
406
78.8k
  UnrollAndJamHintHandler =
407
78.8k
      std::make_unique<PragmaUnrollHintHandler>("unroll_and_jam");
408
78.8k
  PP.AddPragmaHandler(UnrollAndJamHintHandler.get());
409
410
78.8k
  NoUnrollAndJamHintHandler =
411
78.8k
      std::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam");
412
78.8k
  PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get());
413
414
78.8k
  FPHandler = std::make_unique<PragmaFPHandler>();
415
78.8k
  PP.AddPragmaHandler("clang", FPHandler.get());
416
417
78.8k
  AttributePragmaHandler =
418
78.8k
      std::make_unique<PragmaAttributeHandler>(AttrFactory);
419
78.8k
  PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
420
421
78.8k
  MaxTokensHerePragmaHandler = std::make_unique<PragmaMaxTokensHereHandler>();
422
78.8k
  PP.AddPragmaHandler("clang", MaxTokensHerePragmaHandler.get());
423
424
78.8k
  MaxTokensTotalPragmaHandler = std::make_unique<PragmaMaxTokensTotalHandler>();
425
78.8k
  PP.AddPragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
426
78.8k
}
427
428
78.7k
void Parser::resetPragmaHandlers() {
429
  // Remove the pragma handlers we installed.
430
78.7k
  PP.RemovePragmaHandler(AlignHandler.get());
431
78.7k
  AlignHandler.reset();
432
78.7k
  PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
433
78.7k
  GCCVisibilityHandler.reset();
434
78.7k
  PP.RemovePragmaHandler(OptionsHandler.get());
435
78.7k
  OptionsHandler.reset();
436
78.7k
  PP.RemovePragmaHandler(PackHandler.get());
437
78.7k
  PackHandler.reset();
438
78.7k
  PP.RemovePragmaHandler(MSStructHandler.get());
439
78.7k
  MSStructHandler.reset();
440
78.7k
  PP.RemovePragmaHandler(UnusedHandler.get());
441
78.7k
  UnusedHandler.reset();
442
78.7k
  PP.RemovePragmaHandler(WeakHandler.get());
443
78.7k
  WeakHandler.reset();
444
78.7k
  PP.RemovePragmaHandler(RedefineExtnameHandler.get());
445
78.7k
  RedefineExtnameHandler.reset();
446
447
78.7k
  if (getLangOpts().OpenCL) {
448
595
    PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
449
595
    OpenCLExtensionHandler.reset();
450
595
    PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
451
595
  }
452
78.7k
  PP.RemovePragmaHandler(OpenMPHandler.get());
453
78.7k
  OpenMPHandler.reset();
454
455
78.7k
  if (getLangOpts().MicrosoftExt ||
456
68.3k
      getTargetInfo().getTriple().isOSBinFormatELF()) {
457
34.8k
    PP.RemovePragmaHandler(MSCommentHandler.get());
458
34.8k
    MSCommentHandler.reset();
459
34.8k
  }
460
461
78.7k
  PP.RemovePragmaHandler("clang", PCSectionHandler.get());
462
78.7k
  PCSectionHandler.reset();
463
464
78.7k
  PP.RemovePragmaHandler(FloatControlHandler.get());
465
78.7k
  FloatControlHandler.reset();
466
78.7k
  if (getLangOpts().MicrosoftExt) {
467
10.4k
    PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
468
10.4k
    MSDetectMismatchHandler.reset();
469
10.4k
    PP.RemovePragmaHandler(MSPointersToMembers.get());
470
10.4k
    MSPointersToMembers.reset();
471
10.4k
    PP.RemovePragmaHandler(MSVtorDisp.get());
472
10.4k
    MSVtorDisp.reset();
473
10.4k
    PP.RemovePragmaHandler(MSInitSeg.get());
474
10.4k
    MSInitSeg.reset();
475
10.4k
    PP.RemovePragmaHandler(MSDataSeg.get());
476
10.4k
    MSDataSeg.reset();
477
10.4k
    PP.RemovePragmaHandler(MSBSSSeg.get());
478
10.4k
    MSBSSSeg.reset();
479
10.4k
    PP.RemovePragmaHandler(MSConstSeg.get());
480
10.4k
    MSConstSeg.reset();
481
10.4k
    PP.RemovePragmaHandler(MSCodeSeg.get());
482
10.4k
    MSCodeSeg.reset();
483
10.4k
    PP.RemovePragmaHandler(MSSection.get());
484
10.4k
    MSSection.reset();
485
10.4k
    PP.RemovePragmaHandler(MSRuntimeChecks.get());
486
10.4k
    MSRuntimeChecks.reset();
487
10.4k
    PP.RemovePragmaHandler(MSIntrinsic.get());
488
10.4k
    MSIntrinsic.reset();
489
10.4k
    PP.RemovePragmaHandler(MSOptimize.get());
490
10.4k
    MSOptimize.reset();
491
10.4k
  }
492
493
78.7k
  if (getLangOpts().CUDA) {
494
345
    PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get());
495
345
    CUDAForceHostDeviceHandler.reset();
496
345
  }
497
498
78.7k
  PP.RemovePragmaHandler("STDC", FPContractHandler.get());
499
78.7k
  FPContractHandler.reset();
500
501
78.7k
  PP.RemovePragmaHandler("STDC", STDCFenvAccessHandler.get());
502
78.7k
  STDCFenvAccessHandler.reset();
503
504
78.7k
  PP.RemovePragmaHandler("STDC", STDCFenvRoundHandler.get());
505
78.7k
  STDCFenvRoundHandler.reset();
506
507
78.7k
  PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get());
508
78.7k
  STDCCXLIMITHandler.reset();
509
510
78.7k
  PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get());
511
78.7k
  STDCUnknownHandler.reset();
512
513
78.7k
  PP.RemovePragmaHandler("clang", OptimizeHandler.get());
514
78.7k
  OptimizeHandler.reset();
515
516
78.7k
  PP.RemovePragmaHandler("clang", LoopHintHandler.get());
517
78.7k
  LoopHintHandler.reset();
518
519
78.7k
  PP.RemovePragmaHandler(UnrollHintHandler.get());
520
78.7k
  UnrollHintHandler.reset();
521
522
78.7k
  PP.RemovePragmaHandler(NoUnrollHintHandler.get());
523
78.7k
  NoUnrollHintHandler.reset();
524
525
78.7k
  PP.RemovePragmaHandler(UnrollAndJamHintHandler.get());
526
78.7k
  UnrollAndJamHintHandler.reset();
527
528
78.7k
  PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get());
529
78.7k
  NoUnrollAndJamHintHandler.reset();
530
531
78.7k
  PP.RemovePragmaHandler("clang", FPHandler.get());
532
78.7k
  FPHandler.reset();
533
534
78.7k
  PP.RemovePragmaHandler("clang", AttributePragmaHandler.get());
535
78.7k
  AttributePragmaHandler.reset();
536
537
78.7k
  PP.RemovePragmaHandler("clang", MaxTokensHerePragmaHandler.get());
538
78.7k
  MaxTokensHerePragmaHandler.reset();
539
540
78.7k
  PP.RemovePragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
541
78.7k
  MaxTokensTotalPragmaHandler.reset();
542
78.7k
}
543
544
/// Handle the annotation token produced for #pragma unused(...)
545
///
546
/// Each annot_pragma_unused is followed by the argument token so e.g.
547
/// "#pragma unused(x,y)" becomes:
548
/// annot_pragma_unused 'x' annot_pragma_unused 'y'
549
25
void Parser::HandlePragmaUnused() {
550
25
  assert(Tok.is(tok::annot_pragma_unused));
551
25
  SourceLocation UnusedLoc = ConsumeAnnotationToken();
552
25
  Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
553
25
  ConsumeToken(); // The argument token.
554
25
}
555
556
111
void Parser::HandlePragmaVisibility() {
557
111
  assert(Tok.is(tok::annot_pragma_vis));
558
111
  const IdentifierInfo *VisType =
559
111
    static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
560
111
  SourceLocation VisLoc = ConsumeAnnotationToken();
561
111
  Actions.ActOnPragmaVisibility(VisType, VisLoc);
562
111
}
563
564
namespace {
565
struct PragmaPackInfo {
566
  Sema::PragmaMsStackAction Action;
567
  StringRef SlotLabel;
568
  Token Alignment;
569
};
570
} // end anonymous namespace
571
572
331k
void Parser::HandlePragmaPack() {
573
331k
  assert(Tok.is(tok::annot_pragma_pack));
574
331k
  PragmaPackInfo *Info =
575
331k
    static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
576
331k
  SourceLocation PragmaLoc = Tok.getLocation();
577
331k
  ExprResult Alignment;
578
331k
  if (Info->Alignment.is(tok::numeric_constant)) {
579
165k
    Alignment = Actions.ActOnNumericConstant(Info->Alignment);
580
165k
    if (Alignment.isInvalid()) {
581
0
      ConsumeAnnotationToken();
582
0
      return;
583
0
    }
584
331k
  }
585
331k
  Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
586
331k
                          Alignment.get());
587
  // Consume the token after processing the pragma to enable pragma-specific
588
  // #include warnings.
589
331k
  ConsumeAnnotationToken();
590
331k
}
591
592
14
void Parser::HandlePragmaMSStruct() {
593
14
  assert(Tok.is(tok::annot_pragma_msstruct));
594
14
  PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
595
14
      reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
596
14
  Actions.ActOnPragmaMSStruct(Kind);
597
14
  ConsumeAnnotationToken();
598
14
}
599
600
3.63k
void Parser::HandlePragmaAlign() {
601
3.63k
  assert(Tok.is(tok::annot_pragma_align));
602
3.63k
  Sema::PragmaOptionsAlignKind Kind =
603
3.63k
    static_cast<Sema::PragmaOptionsAlignKind>(
604
3.63k
    reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
605
3.63k
  Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation());
606
  // Consume the token after processing the pragma to enable pragma-specific
607
  // #include warnings.
608
3.63k
  ConsumeAnnotationToken();
609
3.63k
}
610
611
20
void Parser::HandlePragmaDump() {
612
20
  assert(Tok.is(tok::annot_pragma_dump));
613
20
  IdentifierInfo *II =
614
20
      reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
615
20
  Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
616
20
  ConsumeAnnotationToken();
617
20
}
618
619
91
void Parser::HandlePragmaWeak() {
620
91
  assert(Tok.is(tok::annot_pragma_weak));
621
91
  SourceLocation PragmaLoc = ConsumeAnnotationToken();
622
91
  Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
623
91
                            Tok.getLocation());
624
91
  ConsumeToken(); // The weak name.
625
91
}
626
627
22
void Parser::HandlePragmaWeakAlias() {
628
22
  assert(Tok.is(tok::annot_pragma_weakalias));
629
22
  SourceLocation PragmaLoc = ConsumeAnnotationToken();
630
22
  IdentifierInfo *WeakName = Tok.getIdentifierInfo();
631
22
  SourceLocation WeakNameLoc = Tok.getLocation();
632
22
  ConsumeToken();
633
22
  IdentifierInfo *AliasName = Tok.getIdentifierInfo();
634
22
  SourceLocation AliasNameLoc = Tok.getLocation();
635
22
  ConsumeToken();
636
22
  Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
637
22
                               WeakNameLoc, AliasNameLoc);
638
639
22
}
640
641
10
void Parser::HandlePragmaRedefineExtname() {
642
10
  assert(Tok.is(tok::annot_pragma_redefine_extname));
643
10
  SourceLocation RedefLoc = ConsumeAnnotationToken();
644
10
  IdentifierInfo *RedefName = Tok.getIdentifierInfo();
645
10
  SourceLocation RedefNameLoc = Tok.getLocation();
646
10
  ConsumeToken();
647
10
  IdentifierInfo *AliasName = Tok.getIdentifierInfo();
648
10
  SourceLocation AliasNameLoc = Tok.getLocation();
649
10
  ConsumeToken();
650
10
  Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
651
10
                                     RedefNameLoc, AliasNameLoc);
652
10
}
653
654
33
void Parser::HandlePragmaFPContract() {
655
33
  assert(Tok.is(tok::annot_pragma_fp_contract));
656
33
  tok::OnOffSwitch OOS =
657
33
    static_cast<tok::OnOffSwitch>(
658
33
    reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
659
660
33
  LangOptions::FPModeKind FPC;
661
33
  switch (OOS) {
662
24
  case tok::OOS_ON:
663
24
    FPC = LangOptions::FPM_On;
664
24
    break;
665
7
  case tok::OOS_OFF:
666
7
    FPC = LangOptions::FPM_Off;
667
7
    break;
668
2
  case tok::OOS_DEFAULT:
669
2
    FPC = getLangOpts().getDefaultFPContractMode();
670
2
    break;
671
33
  }
672
673
33
  SourceLocation PragmaLoc = ConsumeAnnotationToken();
674
33
  Actions.ActOnPragmaFPContract(PragmaLoc, FPC);
675
33
}
676
677
250
void Parser::HandlePragmaFloatControl() {
678
250
  assert(Tok.is(tok::annot_pragma_float_control));
679
680
  // The value that is held on the PragmaFloatControlStack encodes
681
  // the PragmaFloatControl kind and the MSStackAction kind
682
  // into a single 32-bit word. The MsStackAction is the high 16 bits
683
  // and the FloatControl is the lower 16 bits. Use shift and bit-and
684
  // to decode the parts.
685
250
  uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
686
250
  Sema::PragmaMsStackAction Action =
687
250
      static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
688
250
  PragmaFloatControlKind Kind = PragmaFloatControlKind(Value & 0xFFFF);
689
250
  SourceLocation PragmaLoc = ConsumeAnnotationToken();
690
250
  Actions.ActOnPragmaFloatControl(PragmaLoc, Action, Kind);
691
250
}
692
693
18
void Parser::HandlePragmaFEnvAccess() {
694
18
  assert(Tok.is(tok::annot_pragma_fenv_access));
695
18
  tok::OnOffSwitch OOS =
696
18
    static_cast<tok::OnOffSwitch>(
697
18
    reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
698
699
18
  bool IsEnabled;
700
18
  switch (OOS) {
701
10
  case tok::OOS_ON:
702
10
    IsEnabled = true;
703
10
    break;
704
8
  case tok::OOS_OFF:
705
8
    IsEnabled = false;
706
8
    break;
707
0
  case tok::OOS_DEFAULT: // FIXME: Add this cli option when it makes sense.
708
0
    IsEnabled = false;
709
0
    break;
710
18
  }
711
712
18
  SourceLocation PragmaLoc = ConsumeAnnotationToken();
713
18
  Actions.ActOnPragmaFEnvAccess(PragmaLoc, IsEnabled);
714
18
}
715
716
34
void Parser::HandlePragmaFEnvRound() {
717
34
  assert(Tok.is(tok::annot_pragma_fenv_round));
718
34
  auto RM = static_cast<llvm::RoundingMode>(
719
34
      reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
720
721
34
  SourceLocation PragmaLoc = ConsumeAnnotationToken();
722
34
  Actions.setRoundingMode(PragmaLoc, RM);
723
34
}
724
725
StmtResult Parser::HandlePragmaCaptured()
726
57
{
727
57
  assert(Tok.is(tok::annot_pragma_captured));
728
57
  ConsumeAnnotationToken();
729
730
57
  if (Tok.isNot(tok::l_brace)) {
731
1
    PP.Diag(Tok, diag::err_expected) << tok::l_brace;
732
1
    return StmtError();
733
1
  }
734
735
56
  SourceLocation Loc = Tok.getLocation();
736
737
56
  ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |
738
56
                                           Scope::CompoundStmtScope);
739
56
  Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
740
56
                                   /*NumParams=*/1);
741
742
56
  StmtResult R = ParseCompoundStatement();
743
56
  CapturedRegionScope.Exit();
744
745
56
  if (R.isInvalid()) {
746
0
    Actions.ActOnCapturedRegionError();
747
0
    return StmtError();
748
0
  }
749
750
56
  return Actions.ActOnCapturedRegionEnd(R.get());
751
56
}
752
753
namespace {
754
  enum OpenCLExtState : char {
755
    Disable, Enable, Begin, End
756
  };
757
  typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
758
}
759
760
1.71k
void Parser::HandlePragmaOpenCLExtension() {
761
1.71k
  assert(Tok.is(tok::annot_pragma_opencl_extension));
762
1.71k
  OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
763
1.71k
  auto State = Data->second;
764
1.71k
  auto Ident = Data->first;
765
1.71k
  SourceLocation NameLoc = Tok.getLocation();
766
1.71k
  ConsumeAnnotationToken();
767
768
1.71k
  auto &Opt = Actions.getOpenCLOptions();
769
1.71k
  auto Name = Ident->getName();
770
  // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
771
  // overriding all previously issued extension directives, but only if the
772
  // behavior is set to disable."
773
1.71k
  if (Name == "all") {
774
64
    if (State == Disable) {
775
55
      Opt.disableAll();
776
55
      Opt.enableSupportedCore(getLangOpts());
777
9
    } else {
778
9
      PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
779
9
    }
780
1.65k
  } else if (State == Begin) {
781
86
    if (!Opt.isKnown(Name) || 
!Opt.isSupported(Name, getLangOpts())63
) {
782
23
      Opt.support(Name);
783
23
    }
784
86
    Actions.setCurrentOpenCLExtension(Name);
785
1.56k
  } else if (State == End) {
786
90
    if (Name != Actions.getCurrentOpenCLExtension())
787
4
      PP.Diag(NameLoc, diag::warn_pragma_begin_end_mismatch);
788
90
    Actions.setCurrentOpenCLExtension("");
789
1.47k
  } else if (!Opt.isKnown(Name))
790
13
    PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
791
1.46k
  else if (Opt.isSupportedExtension(Name, getLangOpts()))
792
780
    Opt.enable(Name, State == Enable);
793
685
  else if (Opt.isSupportedCore(Name, getLangOpts()))
794
294
    PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
795
391
  else
796
391
    PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
797
1.71k
}
798
799
25
void Parser::HandlePragmaMSPointersToMembers() {
800
25
  assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
801
25
  LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
802
25
      static_cast<LangOptions::PragmaMSPointersToMembersKind>(
803
25
          reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
804
25
  SourceLocation PragmaLoc = ConsumeAnnotationToken();
805
25
  Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
806
25
}
807
808
45
void Parser::HandlePragmaMSVtorDisp() {
809
45
  assert(Tok.is(tok::annot_pragma_ms_vtordisp));
810
45
  uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
811
45
  Sema::PragmaMsStackAction Action =
812
45
      static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
813
45
  MSVtorDispMode Mode = MSVtorDispMode(Value & 0xFFFF);
814
45
  SourceLocation PragmaLoc = ConsumeAnnotationToken();
815
45
  Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
816
45
}
817
818
146
void Parser::HandlePragmaMSPragma() {
819
146
  assert(Tok.is(tok::annot_pragma_ms_pragma));
820
  // Grab the tokens out of the annotation and enter them into the stream.
821
146
  auto TheTokens =
822
146
      (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
823
146
  PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true,
824
146
                      /*IsReinject=*/true);
825
146
  SourceLocation PragmaLocation = ConsumeAnnotationToken();
826
146
  assert(Tok.isAnyIdentifier());
827
146
  StringRef PragmaName = Tok.getIdentifierInfo()->getName();
828
146
  PP.Lex(Tok); // pragma kind
829
830
  // Figure out which #pragma we're dealing with.  The switch has no default
831
  // because lex shouldn't emit the annotation token for unrecognized pragmas.
832
146
  typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
833
146
  PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
834
146
    .Case("data_seg", &Parser::HandlePragmaMSSegment)
835
146
    .Case("bss_seg", &Parser::HandlePragmaMSSegment)
836
146
    .Case("const_seg", &Parser::HandlePragmaMSSegment)
837
146
    .Case("code_seg", &Parser::HandlePragmaMSSegment)
838
146
    .Case("section", &Parser::HandlePragmaMSSection)
839
146
    .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
840
841
146
  if (!(this->*Handler)(PragmaName, PragmaLocation)) {
842
    // Pragma handling failed, and has been diagnosed.  Slurp up the tokens
843
    // until eof (really end of line) to prevent follow-on errors.
844
108
    while (Tok.isNot(tok::eof))
845
62
      PP.Lex(Tok);
846
46
    PP.Lex(Tok);
847
46
  }
848
146
}
849
850
bool Parser::HandlePragmaMSSection(StringRef PragmaName,
851
31
                                   SourceLocation PragmaLocation) {
852
31
  if (Tok.isNot(tok::l_paren)) {
853
1
    PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
854
1
    return false;
855
1
  }
856
30
  PP.Lex(Tok); // (
857
  // Parsing code for pragma section
858
30
  if (Tok.isNot(tok::string_literal)) {
859
2
    PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
860
2
        << PragmaName;
861
2
    return false;
862
2
  }
863
28
  ExprResult StringResult = ParseStringLiteralExpression();
864
28
  if (StringResult.isInvalid())
865
0
    return false; // Already diagnosed.
866
28
  StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
867
28
  if (SegmentName->getCharByteWidth() != 1) {
868
0
    PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
869
0
        << PragmaName;
870
0
    return false;
871
0
  }
872
28
  int SectionFlags = ASTContext::PSF_Read;
873
28
  bool SectionFlagsAreDefault = true;
874
82
  while (Tok.is(tok::comma)) {
875
58
    PP.Lex(Tok); // ,
876
    // Ignore "long" and "short".
877
    // They are undocumented, but widely used, section attributes which appear
878
    // to do nothing.
879
58
    if (Tok.is(tok::kw_long) || 
Tok.is(tok::kw_short)42
) {
880
17
      PP.Lex(Tok); // long/short
881
17
      continue;
882
17
    }
883
884
41
    if (!Tok.isAnyIdentifier()) {
885
2
      PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
886
2
          << PragmaName;
887
2
      return false;
888
2
    }
889
39
    ASTContext::PragmaSectionFlag Flag =
890
39
      llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
891
39
      Tok.getIdentifierInfo()->getName())
892
39
      .Case("read", ASTContext::PSF_Read)
893
39
      .Case("write", ASTContext::PSF_Write)
894
39
      .Case("execute", ASTContext::PSF_Execute)
895
39
      .Case("shared", ASTContext::PSF_Invalid)
896
39
      .Case("nopage", ASTContext::PSF_Invalid)
897
39
      .Case("nocache", ASTContext::PSF_Invalid)
898
39
      .Case("discard", ASTContext::PSF_Invalid)
899
39
      .Case("remove", ASTContext::PSF_Invalid)
900
39
      .Default(ASTContext::PSF_None);
901
39
    if (Flag == ASTContext::PSF_None || 
Flag == ASTContext::PSF_Invalid38
) {
902
2
      PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
903
1
                                  ? diag::warn_pragma_invalid_specific_action
904
1
                                  : diag::warn_pragma_unsupported_action)
905
2
          << PragmaName << Tok.getIdentifierInfo()->getName();
906
2
      return false;
907
2
    }
908
37
    SectionFlags |= Flag;
909
37
    SectionFlagsAreDefault = false;
910
37
    PP.Lex(Tok); // Identifier
911
37
  }
912
  // If no section attributes are specified, the section will be marked as
913
  // read/write.
914
24
  if (SectionFlagsAreDefault)
915
5
    SectionFlags |= ASTContext::PSF_Write;
916
24
  if (Tok.isNot(tok::r_paren)) {
917
2
    PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
918
2
    return false;
919
2
  }
920
22
  PP.Lex(Tok); // )
921
22
  if (Tok.isNot(tok::eof)) {
922
0
    PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
923
0
        << PragmaName;
924
0
    return false;
925
0
  }
926
22
  PP.Lex(Tok); // eof
927
22
  Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
928
22
  return true;
929
22
}
930
931
bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
932
67
                                   SourceLocation PragmaLocation) {
933
67
  if (Tok.isNot(tok::l_paren)) {
934
2
    PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
935
2
    return false;
936
2
  }
937
65
  PP.Lex(Tok); // (
938
65
  Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
939
65
  StringRef SlotLabel;
940
65
  if (Tok.isAnyIdentifier()) {
941
27
    StringRef PushPop = Tok.getIdentifierInfo()->getName();
942
27
    if (PushPop == "push")
943
20
      Action = Sema::PSK_Push;
944
7
    else if (PushPop == "pop")
945
7
      Action = Sema::PSK_Pop;
946
0
    else {
947
0
      PP.Diag(PragmaLocation,
948
0
              diag::warn_pragma_expected_section_push_pop_or_name)
949
0
          << PragmaName;
950
0
      return false;
951
0
    }
952
27
    if (Action != Sema::PSK_Reset) {
953
27
      PP.Lex(Tok); // push | pop
954
27
      if (Tok.is(tok::comma)) {
955
20
        PP.Lex(Tok); // ,
956
        // If we've got a comma, we either need a label or a string.
957
20
        if (Tok.isAnyIdentifier()) {
958
4
          SlotLabel = Tok.getIdentifierInfo()->getName();
959
4
          PP.Lex(Tok); // identifier
960
4
          if (Tok.is(tok::comma))
961
3
            PP.Lex(Tok);
962
1
          else if (Tok.isNot(tok::r_paren)) {
963
0
            PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
964
0
                << PragmaName;
965
0
            return false;
966
0
          }
967
7
        }
968
7
      } else if (Tok.isNot(tok::r_paren)) {
969
0
        PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
970
0
        return false;
971
0
      }
972
65
    }
973
27
  }
974
  // Grab the string literal for our section name.
975
65
  StringLiteral *SegmentName = nullptr;
976
65
  if (Tok.isNot(tok::r_paren)) {
977
53
    if (Tok.isNot(tok::string_literal)) {
978
2
      unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
979
1
          diag::warn_pragma_expected_section_name :
980
1
          diag::warn_pragma_expected_section_label_or_name :
981
2
          diag::warn_pragma_expected_section_push_pop_or_name;
982
4
      PP.Diag(PragmaLocation, DiagID) << PragmaName;
983
4
      return false;
984
4
    }
985
49
    ExprResult StringResult = ParseStringLiteralExpression();
986
49
    if (StringResult.isInvalid())
987
1
      return false; // Already diagnosed.
988
48
    SegmentName = cast<StringLiteral>(StringResult.get());
989
48
    if (SegmentName->getCharByteWidth() != 1) {
990
1
      PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
991
1
          << PragmaName;
992
1
      return false;
993
1
    }
994
    // Setting section "" has no effect
995
47
    if (SegmentName->getLength())
996
47
      Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
997
47
  }
998
59
  if (Tok.isNot(tok::r_paren)) {
999
2
    PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
1000
2
    return false;
1001
2
  }
1002
57
  PP.Lex(Tok); // )
1003
57
  if (Tok.isNot(tok::eof)) {
1004
0
    PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
1005
0
        << PragmaName;
1006
0
    return false;
1007
0
  }
1008
57
  PP.Lex(Tok); // eof
1009
57
  Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
1010
57
                           SegmentName, PragmaName);
1011
57
  return true;
1012
57
}
1013
1014
// #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
1015
bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
1016
48
                                   SourceLocation PragmaLocation) {
1017
48
  if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
1018
3
    PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
1019
3
    return false;
1020
3
  }
1021
1022
45
  if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
1023
45
                       PragmaName))
1024
6
    return false;
1025
1026
  // Parse either the known section names or the string section name.
1027
39
  StringLiteral *SegmentName = nullptr;
1028
39
  if (Tok.isAnyIdentifier()) {
1029
17
    auto *II = Tok.getIdentifierInfo();
1030
17
    StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
1031
17
                            .Case("compiler", "\".CRT$XCC\"")
1032
17
                            .Case("lib", "\".CRT$XCL\"")
1033
17
                            .Case("user", "\".CRT$XCU\"")
1034
17
                            .Default("");
1035
1036
17
    if (!Section.empty()) {
1037
      // Pretend the user wrote the appropriate string literal here.
1038
17
      Token Toks[1];
1039
17
      Toks[0].startToken();
1040
17
      Toks[0].setKind(tok::string_literal);
1041
17
      Toks[0].setLocation(Tok.getLocation());
1042
17
      Toks[0].setLiteralData(Section.data());
1043
17
      Toks[0].setLength(Section.size());
1044
17
      SegmentName =
1045
17
          cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
1046
17
      PP.Lex(Tok);
1047
17
    }
1048
22
  } else if (Tok.is(tok::string_literal)) {
1049
16
    ExprResult StringResult = ParseStringLiteralExpression();
1050
16
    if (StringResult.isInvalid())
1051
3
      return false;
1052
13
    SegmentName = cast<StringLiteral>(StringResult.get());
1053
13
    if (SegmentName->getCharByteWidth() != 1) {
1054
3
      PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1055
3
          << PragmaName;
1056
3
      return false;
1057
3
    }
1058
    // FIXME: Add support for the '[, func-name]' part of the pragma.
1059
13
  }
1060
1061
33
  if (!SegmentName) {
1062
6
    PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
1063
6
    return false;
1064
6
  }
1065
1066
27
  if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
1067
27
                       PragmaName) ||
1068
24
      ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
1069
24
                       PragmaName))
1070
6
    return false;
1071
1072
21
  Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
1073
21
  return true;
1074
21
}
1075
1076
namespace {
1077
struct PragmaLoopHintInfo {
1078
  Token PragmaName;
1079
  Token Option;
1080
  ArrayRef<Token> Toks;
1081
};
1082
} // end anonymous namespace
1083
1084
2
static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
1085
2
  StringRef Str = PragmaName.getIdentifierInfo()->getName();
1086
2
  std::string ClangLoopStr = (llvm::Twine("clang loop ") + Str).str();
1087
2
  return std::string(llvm::StringSwitch<StringRef>(Str)
1088
2
                         .Case("loop", ClangLoopStr)
1089
2
                         .Case("unroll_and_jam", Str)
1090
2
                         .Case("unroll", Str)
1091
2
                         .Default(""));
1092
2
}
1093
1094
377
bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
1095
377
  assert(Tok.is(tok::annot_pragma_loop_hint));
1096
377
  PragmaLoopHintInfo *Info =
1097
377
      static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
1098
1099
377
  IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
1100
377
  Hint.PragmaNameLoc = IdentifierLoc::create(
1101
377
      Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
1102
1103
  // It is possible that the loop hint has no option identifier, such as
1104
  // #pragma unroll(4).
1105
377
  IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
1106
297
                                   ? Info->Option.getIdentifierInfo()
1107
80
                                   : nullptr;
1108
377
  Hint.OptionLoc = IdentifierLoc::create(
1109
377
      Actions.Context, Info->Option.getLocation(), OptionInfo);
1110
1111
377
  llvm::ArrayRef<Token> Toks = Info->Toks;
1112
1113
  // Return a valid hint if pragma unroll or nounroll were specified
1114
  // without an argument.
1115
377
  auto IsLoopHint = llvm::StringSwitch<bool>(PragmaNameInfo->getName())
1116
377
                        .Cases("unroll", "nounroll", "unroll_and_jam",
1117
377
                               "nounroll_and_jam", true)
1118
377
                        .Default(false);
1119
1120
377
  if (Toks.empty() && 
IsLoopHint34
) {
1121
34
    ConsumeAnnotationToken();
1122
34
    Hint.Range = Info->PragmaName.getLocation();
1123
34
    return true;
1124
34
  }
1125
1126
  // The constant expression is always followed by an eof token, which increases
1127
  // the TokSize by 1.
1128
343
  assert(!Toks.empty() &&
1129
343
         "PragmaLoopHintInfo::Toks must contain at least one token.");
1130
1131
  // If no option is specified the argument is assumed to be a constant expr.
1132
343
  bool OptionUnroll = false;
1133
343
  bool OptionUnrollAndJam = false;
1134
343
  bool OptionDistribute = false;
1135
343
  bool OptionPipelineDisabled = false;
1136
343
  bool StateOption = false;
1137
343
  if (OptionInfo) { // Pragma Unroll does not specify an option.
1138
297
    OptionUnroll = OptionInfo->isStr("unroll");
1139
297
    OptionUnrollAndJam = OptionInfo->isStr("unroll_and_jam");
1140
297
    OptionDistribute = OptionInfo->isStr("distribute");
1141
297
    OptionPipelineDisabled = OptionInfo->isStr("pipeline");
1142
297
    StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
1143
297
                      .Case("vectorize", true)
1144
297
                      .Case("interleave", true)
1145
297
                      .Case("vectorize_predicate", true)
1146
297
                      .Default(false) ||
1147
201
                  OptionUnroll || 
OptionUnrollAndJam162
||
OptionDistribute162
||
1148
137
                  OptionPipelineDisabled;
1149
297
  }
1150
1151
343
  bool AssumeSafetyArg = !OptionUnroll && 
!OptionUnrollAndJam304
&&
1152
304
                         !OptionDistribute && 
!OptionPipelineDisabled279
;
1153
  // Verify loop hint has an argument.
1154
343
  if (Toks[0].is(tok::eof)) {
1155
7
    ConsumeAnnotationToken();
1156
7
    Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
1157
7
        << /*StateArgument=*/StateOption
1158
7
        << /*FullKeyword=*/(OptionUnroll || 
OptionUnrollAndJam6
)
1159
7
        << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
1160
7
    return false;
1161
7
  }
1162
1163
  // Validate the argument.
1164
336
  if (StateOption) {
1165
165
    ConsumeAnnotationToken();
1166
165
    SourceLocation StateLoc = Toks[0].getLocation();
1167
165
    IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
1168
1169
165
    bool Valid = StateInfo &&
1170
162
                 llvm::StringSwitch<bool>(StateInfo->getName())
1171
162
                     .Case("disable", true)
1172
162
                     .Case("enable", !OptionPipelineDisabled)
1173
162
                     .Case("full", OptionUnroll || 
OptionUnrollAndJam125
)
1174
162
                     .Case("assume_safety", AssumeSafetyArg)
1175
162
                     .Default(false);
1176
165
    if (!Valid) {
1177
14
      if (OptionPipelineDisabled) {
1178
2
        Diag(Toks[0].getLocation(), diag::err_pragma_pipeline_invalid_keyword);
1179
12
      } else {
1180
12
        Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
1181
12
            << /*FullKeyword=*/(OptionUnroll || 
OptionUnrollAndJam8
)
1182
12
            << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
1183
12
      }
1184
14
      return false;
1185
14
    }
1186
151
    if (Toks.size() > 2)
1187
0
      Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1188
0
          << PragmaLoopHintString(Info->PragmaName, Info->Option);
1189
151
    Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1190
171
  } else if (OptionInfo && 
OptionInfo->getName() == "vectorize_width"127
) {
1191
56
    PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
1192
56
                        /*IsReinject=*/false);
1193
56
    ConsumeAnnotationToken();
1194
1195
56
    SourceLocation StateLoc = Toks[0].getLocation();
1196
56
    IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
1197
30
    StringRef IsScalableStr = StateInfo ? 
StateInfo->getName()26
: "";
1198
1199
    // Look for vectorize_width(fixed|scalable)
1200
56
    if (IsScalableStr == "scalable" || 
IsScalableStr == "fixed"53
) {
1201
6
      PP.Lex(Tok); // Identifier
1202
1203
6
      if (Toks.size() > 2) {
1204
0
        Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1205
0
            << PragmaLoopHintString(Info->PragmaName, Info->Option);
1206
0
        while (Tok.isNot(tok::eof))
1207
0
          ConsumeAnyToken();
1208
0
      }
1209
1210
6
      Hint.StateLoc =
1211
6
          IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1212
1213
6
      ConsumeToken(); // Consume the constant expression eof terminator.
1214
50
    } else {
1215
      // Enter constant expression including eof terminator into token stream.
1216
50
      ExprResult R = ParseConstantExpression();
1217
1218
50
      if (R.isInvalid() && 
!Tok.is(tok::comma)5
)
1219
5
        Diag(Toks[0].getLocation(),
1220
5
             diag::note_pragma_loop_invalid_vectorize_option);
1221
1222
50
      bool Arg2Error = false;
1223
50
      if (Tok.is(tok::comma)) {
1224
6
        PP.Lex(Tok); // ,
1225
1226
6
        StateInfo = Tok.getIdentifierInfo();
1227
6
        IsScalableStr = StateInfo->getName();
1228
1229
6
        if (IsScalableStr != "scalable" && 
IsScalableStr != "fixed"2
) {
1230
0
          Diag(Tok.getLocation(),
1231
0
               diag::err_pragma_loop_invalid_vectorize_option);
1232
0
          Arg2Error = true;
1233
0
        } else
1234
6
          Hint.StateLoc =
1235
6
              IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1236
1237
6
        PP.Lex(Tok); // Identifier
1238
6
      }
1239
1240
      // Tokens following an error in an ill-formed constant expression will
1241
      // remain in the token stream and must be removed.
1242
50
      if (Tok.isNot(tok::eof)) {
1243
0
        Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1244
0
            << PragmaLoopHintString(Info->PragmaName, Info->Option);
1245
0
        while (Tok.isNot(tok::eof))
1246
0
          ConsumeAnyToken();
1247
0
      }
1248
1249
50
      ConsumeToken(); // Consume the constant expression eof terminator.
1250
1251
50
      if (Arg2Error || R.isInvalid() ||
1252
45
          Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
1253
8
        return false;
1254
1255
      // Argument is a constant expression with an integer type.
1256
42
      Hint.ValueExpr = R.get();
1257
42
    }
1258
115
  } else {
1259
    // Enter constant expression including eof terminator into token stream.
1260
115
    PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
1261
115
                        /*IsReinject=*/false);
1262
115
    ConsumeAnnotationToken();
1263
115
    ExprResult R = ParseConstantExpression();
1264
1265
    // Tokens following an error in an ill-formed constant expression will
1266
    // remain in the token stream and must be removed.
1267
115
    if (Tok.isNot(tok::eof)) {
1268
2
      Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1269
2
          << PragmaLoopHintString(Info->PragmaName, Info->Option);
1270
4
      while (Tok.isNot(tok::eof))
1271
2
        ConsumeAnyToken();
1272
2
    }
1273
1274
115
    ConsumeToken(); // Consume the constant expression eof terminator.
1275
1276
115
    if (R.isInvalid() ||
1277
108
        Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
1278
19
      return false;
1279
1280
    // Argument is a constant expression with an integer type.
1281
96
    Hint.ValueExpr = R.get();
1282
96
  }
1283
1284
295
  Hint.Range = SourceRange(Info->PragmaName.getLocation(),
1285
295
                           Info->Toks.back().getLocation());
1286
295
  return true;
1287
336
}
1288
1289
namespace {
1290
struct PragmaAttributeInfo {
1291
  enum ActionType { Push, Pop, Attribute };
1292
  ParsedAttributes &Attributes;
1293
  ActionType Action;
1294
  const IdentifierInfo *Namespace = nullptr;
1295
  ArrayRef<Token> Tokens;
1296
1297
3.11k
  PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
1298
};
1299
1300
#include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
1301
1302
} // end anonymous namespace
1303
1304
12.2k
static StringRef getIdentifier(const Token &Tok) {
1305
12.2k
  if (Tok.is(tok::identifier))
1306
11.3k
    return Tok.getIdentifierInfo()->getName();
1307
938
  const char *S = tok::getKeywordSpelling(Tok.getKind());
1308
938
  if (!S)
1309
13
    return "";
1310
925
  return S;
1311
925
}
1312
1313
11.0k
static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) {
1314
11.0k
  using namespace attr;
1315
11.0k
  switch (Rule) {
1316
0
#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract)                           \
1317
11.0k
  case Value:                                                                  \
1318
11.0k
    return IsAbstract;
1319
0
#include "clang/Basic/AttrSubMatchRulesList.inc"
1320
11.0k
  }
1321
11.0k
  
llvm_unreachable0
("Invalid attribute subject match rule");
1322
0
  return false;
1323
11.0k
}
1324
1325
static void diagnoseExpectedAttributeSubjectSubRule(
1326
    Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1327
5
    SourceLocation SubRuleLoc) {
1328
5
  auto Diagnostic =
1329
5
      PRef.Diag(SubRuleLoc,
1330
5
                diag::err_pragma_attribute_expected_subject_sub_identifier)
1331
5
      << PrimaryRuleName;
1332
5
  if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1333
3
    Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1334
2
  else
1335
2
    Diagnostic << /*SubRulesSupported=*/0;
1336
5
}
1337
1338
static void diagnoseUnknownAttributeSubjectSubRule(
1339
    Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1340
7
    StringRef SubRuleName, SourceLocation SubRuleLoc) {
1341
1342
7
  auto Diagnostic =
1343
7
      PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)
1344
7
      << SubRuleName << PrimaryRuleName;
1345
7
  if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1346
4
    Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1347
3
  else
1348
3
    Diagnostic << /*SubRulesSupported=*/0;
1349
7
}
1350
1351
bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
1352
    attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,
1353
1.09k
    SourceLocation &LastMatchRuleEndLoc) {
1354
1.09k
  bool IsAny = false;
1355
1.09k
  BalancedDelimiterTracker AnyParens(*this, tok::l_paren);
1356
1.09k
  if (getIdentifier(Tok) == "any") {
1357
1.01k
    AnyLoc = ConsumeToken();
1358
1.01k
    IsAny = true;
1359
1.01k
    if (AnyParens.expectAndConsume())
1360
3
      return true;
1361
1.08k
  }
1362
1363
11.0k
  
do 1.08k
{
1364
    // Parse the subject matcher rule.
1365
11.0k
    StringRef Name = getIdentifier(Tok);
1366
11.0k
    if (Name.empty()) {
1367
6
      Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);
1368
6
      return true;
1369
6
    }
1370
11.0k
    std::pair<Optional<attr::SubjectMatchRule>,
1371
11.0k
              Optional<attr::SubjectMatchRule> (*)(StringRef, bool)>
1372
11.0k
        Rule = isAttributeSubjectMatchRule(Name);
1373
11.0k
    if (!Rule.first) {
1374
4
      Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;
1375
4
      return true;
1376
4
    }
1377
11.0k
    attr::SubjectMatchRule PrimaryRule = *Rule.first;
1378
11.0k
    SourceLocation RuleLoc = ConsumeToken();
1379
1380
11.0k
    BalancedDelimiterTracker Parens(*this, tok::l_paren);
1381
11.0k
    if (isAbstractAttrMatcherRule(PrimaryRule)) {
1382
5
      if (Parens.expectAndConsume())
1383
2
        return true;
1384
11.0k
    } else if (Parens.consumeOpen()) {
1385
10.8k
      if (!SubjectMatchRules
1386
10.8k
               .insert(
1387
10.8k
                   std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))
1388
10.8k
               .second)
1389
7
        Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1390
7
            << Name
1391
7
            << FixItHint::CreateRemoval(SourceRange(
1392
4
                   RuleLoc, Tok.is(tok::comma) ? 
Tok.getLocation()3
: RuleLoc));
1393
10.8k
      LastMatchRuleEndLoc = RuleLoc;
1394
10.8k
      continue;
1395
10.8k
    }
1396
1397
    // Parse the sub-rules.
1398
107
    StringRef SubRuleName = getIdentifier(Tok);
1399
107
    if (SubRuleName.empty()) {
1400
3
      diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1401
3
                                              Tok.getLocation());
1402
3
      return true;
1403
3
    }
1404
104
    attr::SubjectMatchRule SubRule;
1405
104
    if (SubRuleName == "unless") {
1406
49
      SourceLocation SubRuleLoc = ConsumeToken();
1407
49
      BalancedDelimiterTracker Parens(*this, tok::l_paren);
1408
49
      if (Parens.expectAndConsume())
1409
2
        return true;
1410
47
      SubRuleName = getIdentifier(Tok);
1411
47
      if (SubRuleName.empty()) {
1412
2
        diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1413
2
                                                SubRuleLoc);
1414
2
        return true;
1415
2
      }
1416
45
      auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);
1417
45
      if (!SubRuleOrNone) {
1418
3
        std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";
1419
3
        diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1420
3
                                               SubRuleUnlessName, SubRuleLoc);
1421
3
        return true;
1422
3
      }
1423
42
      SubRule = *SubRuleOrNone;
1424
42
      ConsumeToken();
1425
42
      if (Parens.consumeClose())
1426
1
        return true;
1427
55
    } else {
1428
55
      auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);
1429
55
      if (!SubRuleOrNone) {
1430
4
        diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1431
4
                                               SubRuleName, Tok.getLocation());
1432
4
        return true;
1433
4
      }
1434
51
      SubRule = *SubRuleOrNone;
1435
51
      ConsumeToken();
1436
51
    }
1437
92
    SourceLocation RuleEndLoc = Tok.getLocation();
1438
92
    LastMatchRuleEndLoc = RuleEndLoc;
1439
92
    if (Parens.consumeClose())
1440
1
      return true;
1441
91
    if (!SubjectMatchRules
1442
91
             .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))
1443
8
             .second) {
1444
8
      Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1445
8
          << attr::getSubjectMatchRuleSpelling(SubRule)
1446
8
          << FixItHint::CreateRemoval(SourceRange(
1447
5
                 RuleLoc, Tok.is(tok::comma) ? 
Tok.getLocation()3
: RuleEndLoc));
1448
8
      continue;
1449
8
    }
1450
10.9k
  } while (IsAny && 
TryConsumeToken(tok::comma)10.9k
);
1451
1452
1.05k
  if (IsAny)
1453
992
    if (AnyParens.consumeClose())
1454
2
      return true;
1455
1456
1.05k
  return false;
1457
1.05k
}
1458
1459
namespace {
1460
1461
/// Describes the stage at which attribute subject rule parsing was interrupted.
1462
enum class MissingAttributeSubjectRulesRecoveryPoint {
1463
  Comma,
1464
  ApplyTo,
1465
  Equals,
1466
  Any,
1467
  None,
1468
};
1469
1470
MissingAttributeSubjectRulesRecoveryPoint
1471
40
getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
1472
40
  if (const auto *II = Tok.getIdentifierInfo()) {
1473
17
    if (II->isStr("apply_to"))
1474
2
      return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
1475
15
    if (II->isStr("any"))
1476
6
      return MissingAttributeSubjectRulesRecoveryPoint::Any;
1477
32
  }
1478
32
  if (Tok.is(tok::equal))
1479
5
    return MissingAttributeSubjectRulesRecoveryPoint::Equals;
1480
27
  return MissingAttributeSubjectRulesRecoveryPoint::None;
1481
27
}
1482
1483
/// Creates a diagnostic for the attribute subject rule parsing diagnostic that
1484
/// suggests the possible attribute subject rules in a fix-it together with
1485
/// any other missing tokens.
1486
DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
1487
    unsigned DiagID, ParsedAttr &Attribute,
1488
40
    MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
1489
40
  SourceLocation Loc = PRef.getEndOfPreviousToken();
1490
40
  if (Loc.isInvalid())
1491
0
    Loc = PRef.getCurToken().getLocation();
1492
40
  auto Diagnostic = PRef.Diag(Loc, DiagID);
1493
40
  std::string FixIt;
1494
40
  MissingAttributeSubjectRulesRecoveryPoint EndPoint =
1495
40
      getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());
1496
40
  if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)
1497
18
    FixIt = ", ";
1498
40
  if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&
1499
33
      EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo)
1500
31
    FixIt += "apply_to";
1501
40
  if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&
1502
40
      EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)
1503
33
    FixIt += " = ";
1504
40
  SourceRange FixItRange(Loc);
1505
40
  if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
1506
    // Gather the subject match rules that are supported by the attribute.
1507
27
    SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> SubjectMatchRuleSet;
1508
27
    Attribute.getMatchRules(PRef.getLangOpts(), SubjectMatchRuleSet);
1509
27
    if (SubjectMatchRuleSet.empty()) {
1510
      // FIXME: We can emit a "fix-it" with a subject list placeholder when
1511
      // placeholders will be supported by the fix-its.
1512
9
      return Diagnostic;
1513
9
    }
1514
18
    FixIt += "any(";
1515
18
    bool NeedsComma = false;
1516
69
    for (const auto &I : SubjectMatchRuleSet) {
1517
      // Ensure that the missing rule is reported in the fix-it only when it's
1518
      // supported in the current language mode.
1519
69
      if (!I.second)
1520
1
        continue;
1521
68
      if (NeedsComma)
1522
50
        FixIt += ", ";
1523
18
      else
1524
18
        NeedsComma = true;
1525
68
      FixIt += attr::getSubjectMatchRuleSpelling(I.first);
1526
68
    }
1527
18
    FixIt += ")";
1528
    // Check if we need to remove the range
1529
18
    PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);
1530
18
    FixItRange.setEnd(PRef.getCurToken().getLocation());
1531
18
  }
1532
31
  if (FixItRange.getBegin() == FixItRange.getEnd())
1533
18
    Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);
1534
13
  else
1535
13
    Diagnostic << FixItHint::CreateReplacement(
1536
13
        CharSourceRange::getCharRange(FixItRange), FixIt);
1537
31
  return Diagnostic;
1538
40
}
1539
1540
} // end anonymous namespace
1541
1542
3.09k
void Parser::HandlePragmaAttribute() {
1543
3.09k
  assert(Tok.is(tok::annot_pragma_attribute) &&
1544
3.09k
         "Expected #pragma attribute annotation token");
1545
3.09k
  SourceLocation PragmaLoc = Tok.getLocation();
1546
3.09k
  auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
1547
3.09k
  if (Info->Action == PragmaAttributeInfo::Pop) {
1548
1.04k
    ConsumeAnnotationToken();
1549
1.04k
    Actions.ActOnPragmaAttributePop(PragmaLoc, Info->Namespace);
1550
1.04k
    return;
1551
1.04k
  }
1552
  // Parse the actual attribute with its arguments.
1553
2.04k
  assert((Info->Action == PragmaAttributeInfo::Push ||
1554
2.04k
          Info->Action == PragmaAttributeInfo::Attribute) &&
1555
2.04k
         "Unexpected #pragma attribute command");
1556
1557
2.04k
  if (Info->Action == PragmaAttributeInfo::Push && 
Info->Tokens.empty()1.15k
) {
1558
890
    ConsumeAnnotationToken();
1559
890
    Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
1560
890
    return;
1561
890
  }
1562
1563
1.15k
  PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false,
1564
1.15k
                      /*IsReinject=*/false);
1565
1.15k
  ConsumeAnnotationToken();
1566
1567
1.15k
  ParsedAttributes &Attrs = Info->Attributes;
1568
1.15k
  Attrs.clearListOnly();
1569
1570
99
  auto SkipToEnd = [this]() {
1571
99
    SkipUntil(tok::eof, StopBeforeMatch);
1572
99
    ConsumeToken();
1573
99
  };
1574
1575
1.15k
  if (Tok.is(tok::l_square) && 
NextToken().is(tok::l_square)23
) {
1576
    // Parse the CXX11 style attribute.
1577
23
    ParseCXX11AttributeSpecifier(Attrs);
1578
1.13k
  } else if (Tok.is(tok::kw___attribute)) {
1579
1.12k
    ConsumeToken();
1580
1.12k
    if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
1581
1.12k
                         "attribute"))
1582
1
      return SkipToEnd();
1583
1.12k
    if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))
1584
1
      return SkipToEnd();
1585
1586
1.12k
    if (Tok.isNot(tok::identifier)) {
1587
2
      Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);
1588
2
      SkipToEnd();
1589
2
      return;
1590
2
    }
1591
1.11k
    IdentifierInfo *AttrName = Tok.getIdentifierInfo();
1592
1.11k
    SourceLocation AttrNameLoc = ConsumeToken();
1593
1594
1.11k
    if (Tok.isNot(tok::l_paren))
1595
30
      Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
1596
30
                   ParsedAttr::AS_GNU);
1597
1.08k
    else
1598
1.08k
      ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
1599
1.08k
                            /*ScopeName=*/nullptr,
1600
1.08k
                            /*ScopeLoc=*/SourceLocation(), ParsedAttr::AS_GNU,
1601
1.08k
                            /*Declarator=*/nullptr);
1602
1603
1.11k
    if (ExpectAndConsume(tok::r_paren))
1604
2
      return SkipToEnd();
1605
1.11k
    if (ExpectAndConsume(tok::r_paren))
1606
1
      return SkipToEnd();
1607
10
  } else if (Tok.is(tok::kw___declspec)) {
1608
4
    ParseMicrosoftDeclSpecs(Attrs);
1609
6
  } else {
1610
6
    Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
1611
6
    if (Tok.getIdentifierInfo()) {
1612
      // If we suspect that this is an attribute suggest the use of
1613
      // '__attribute__'.
1614
5
      if (ParsedAttr::getParsedKind(
1615
5
              Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
1616
4
              ParsedAttr::AS_GNU) != ParsedAttr::UnknownAttribute) {
1617
4
        SourceLocation InsertStartLoc = Tok.getLocation();
1618
4
        ConsumeToken();
1619
4
        if (Tok.is(tok::l_paren)) {
1620
2
          ConsumeAnyToken();
1621
2
          SkipUntil(tok::r_paren, StopBeforeMatch);
1622
2
          if (Tok.isNot(tok::r_paren))
1623
0
            return SkipToEnd();
1624
4
        }
1625
4
        Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)
1626
4
            << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")
1627
4
            << FixItHint::CreateInsertion(Tok.getEndLoc(), "))");
1628
4
      }
1629
5
    }
1630
6
    SkipToEnd();
1631
6
    return;
1632
1.14k
  }
1633
1634
1.14k
  if (Attrs.empty() || 
Attrs.begin()->isInvalid()1.13k
) {
1635
4
    SkipToEnd();
1636
4
    return;
1637
4
  }
1638
1639
  // Ensure that we don't have more than one attribute.
1640
1.13k
  if (Attrs.size() > 1) {
1641
3
    SourceLocation Loc = Attrs[1].getLoc();
1642
3
    Diag(Loc, diag::err_pragma_attribute_multiple_attributes);
1643
3
    SkipToEnd();
1644
3
    return;
1645
3
  }
1646
1647
1.13k
  ParsedAttr &Attribute = *Attrs.begin();
1648
1.13k
  if (!Attribute.isSupportedByPragmaAttribute()) {
1649
5
    Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
1650
5
        << Attribute;
1651
5
    SkipToEnd();
1652
5
    return;
1653
5
  }
1654
1655
  // Parse the subject-list.
1656
1.13k
  if (!TryConsumeToken(tok::comma)) {
1657
18
    createExpectedAttributeSubjectRulesTokenDiagnostic(
1658
18
        diag::err_expected, Attribute,
1659
18
        MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)
1660
18
        << tok::comma;
1661
18
    SkipToEnd();
1662
18
    return;
1663
18
  }
1664
1665
1.11k
  if (Tok.isNot(tok::identifier)) {
1666
8
    createExpectedAttributeSubjectRulesTokenDiagnostic(
1667
8
        diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1668
8
        MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1669
8
    SkipToEnd();
1670
8
    return;
1671
8
  }
1672
1.10k
  const IdentifierInfo *II = Tok.getIdentifierInfo();
1673
1.10k
  if (!II->isStr("apply_to")) {
1674
7
    createExpectedAttributeSubjectRulesTokenDiagnostic(
1675
7
        diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1676
7
        MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1677
7
    SkipToEnd();
1678
7
    return;
1679
7
  }
1680
1.09k
  ConsumeToken();
1681
1682
1.09k
  if (!TryConsumeToken(tok::equal)) {
1683
7
    createExpectedAttributeSubjectRulesTokenDiagnostic(
1684
7
        diag::err_expected, Attribute,
1685
7
        MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)
1686
7
        << tok::equal;
1687
7
    SkipToEnd();
1688
7
    return;
1689
7
  }
1690
1691
1.09k
  attr::ParsedSubjectMatchRuleSet SubjectMatchRules;
1692
1.09k
  SourceLocation AnyLoc, LastMatchRuleEndLoc;
1693
1.09k
  if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,
1694
33
                                              LastMatchRuleEndLoc)) {
1695
33
    SkipToEnd();
1696
33
    return;
1697
33
  }
1698
1699
  // Tokens following an ill-formed attribute will remain in the token stream
1700
  // and must be removed.
1701
1.05k
  if (Tok.isNot(tok::eof)) {
1702
1
    Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
1703
1
    SkipToEnd();
1704
1
    return;
1705
1
  }
1706
1707
  // Consume the eof terminator token.
1708
1.05k
  ConsumeToken();
1709
1710
  // Handle a mixed push/attribute by desurging to a push, then an attribute.
1711
1.05k
  if (Info->Action == PragmaAttributeInfo::Push)
1712
165
    Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
1713
1714
1.05k
  Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc,
1715
1.05k
                                        std::move(SubjectMatchRules));
1716
1.05k
}
1717
1718
// #pragma GCC visibility comes in two variants:
1719
//   'push' '(' [visibility] ')'
1720
//   'pop'
1721
void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
1722
                                              PragmaIntroducer Introducer,
1723
116
                                              Token &VisTok) {
1724
116
  SourceLocation VisLoc = VisTok.getLocation();
1725
1726
116
  Token Tok;
1727
116
  PP.LexUnexpandedToken(Tok);
1728
1729
116
  const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
1730
1731
116
  const IdentifierInfo *VisType;
1732
116
  if (PushPop && PushPop->isStr("pop")) {
1733
55
    VisType = nullptr;
1734
61
  } else if (PushPop && PushPop->isStr("push")) {
1735
60
    PP.LexUnexpandedToken(Tok);
1736
60
    if (Tok.isNot(tok::l_paren)) {
1737
1
      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
1738
1
        << "visibility";
1739
1
      return;
1740
1
    }
1741
59
    PP.LexUnexpandedToken(Tok);
1742
59
    VisType = Tok.getIdentifierInfo();
1743
59
    if (!VisType) {
1744
1
      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1745
1
        << "visibility";
1746
1
      return;
1747
1
    }
1748
58
    PP.LexUnexpandedToken(Tok);
1749
58
    if (Tok.isNot(tok::r_paren)) {
1750
1
      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
1751
1
        << "visibility";
1752
1
      return;
1753
1
    }
1754
1
  } else {
1755
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1756
1
      << "visibility";
1757
1
    return;
1758
1
  }
1759
112
  SourceLocation EndLoc = Tok.getLocation();
1760
112
  PP.LexUnexpandedToken(Tok);
1761
112
  if (Tok.isNot(tok::eod)) {
1762
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1763
1
      << "visibility";
1764
1
    return;
1765
1
  }
1766
1767
111
  auto Toks = std::make_unique<Token[]>(1);
1768
111
  Toks[0].startToken();
1769
111
  Toks[0].setKind(tok::annot_pragma_vis);
1770
111
  Toks[0].setLocation(VisLoc);
1771
111
  Toks[0].setAnnotationEndLoc(EndLoc);
1772
111
  Toks[0].setAnnotationValue(
1773
111
      const_cast<void *>(static_cast<const void *>(VisType)));
1774
111
  PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true,
1775
111
                      /*IsReinject=*/false);
1776
111
}
1777
1778
// #pragma pack(...) comes in the following delicious flavors:
1779
//   pack '(' [integer] ')'
1780
//   pack '(' 'show' ')'
1781
//   pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
1782
void PragmaPackHandler::HandlePragma(Preprocessor &PP,
1783
                                     PragmaIntroducer Introducer,
1784
331k
                                     Token &PackTok) {
1785
331k
  SourceLocation PackLoc = PackTok.getLocation();
1786
1787
331k
  Token Tok;
1788
331k
  PP.Lex(Tok);
1789
331k
  if (Tok.isNot(tok::l_paren)) {
1790
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
1791
1
    return;
1792
1
  }
1793
1794
331k
  Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
1795
331k
  StringRef SlotLabel;
1796
331k
  Token Alignment;
1797
331k
  Alignment.startToken();
1798
331k
  PP.Lex(Tok);
1799
331k
  if (Tok.is(tok::numeric_constant)) {
1800
2.45k
    Alignment = Tok;
1801
1802
2.45k
    PP.Lex(Tok);
1803
1804
    // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
1805
    // the push/pop stack.
1806
    // In Apple gcc/XL, #pragma pack(4) is equivalent to #pragma pack(push, 4)
1807
2.45k
    Action = (PP.getLangOpts().ApplePragmaPack || 
PP.getLangOpts().XLPragmaPack2.44k
)
1808
41
                 ? Sema::PSK_Push_Set
1809
2.40k
                 : Sema::PSK_Set;
1810
329k
  } else if (Tok.is(tok::identifier)) {
1811
326k
    const IdentifierInfo *II = Tok.getIdentifierInfo();
1812
326k
    if (II->isStr("show")) {
1813
80
      Action = Sema::PSK_Show;
1814
80
      PP.Lex(Tok);
1815
326k
    } else {
1816
326k
      if (II->isStr("push")) {
1817
163k
        Action = Sema::PSK_Push;
1818
163k
      } else if (II->isStr("pop")) {
1819
163k
        Action = Sema::PSK_Pop;
1820
1
      } else {
1821
1
        PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
1822
1
        return;
1823
1
      }
1824
326k
      PP.Lex(Tok);
1825
1826
326k
      if (Tok.is(tok::comma)) {
1827
163k
        PP.Lex(Tok);
1828
1829
163k
        if (Tok.is(tok::numeric_constant)) {
1830
163k
          Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
1831
163k
          Alignment = Tok;
1832
1833
163k
          PP.Lex(Tok);
1834
28
        } else if (Tok.is(tok::identifier)) {
1835
24
          SlotLabel = Tok.getIdentifierInfo()->getName();
1836
24
          PP.Lex(Tok);
1837
1838
24
          if (Tok.is(tok::comma)) {
1839
14
            PP.Lex(Tok);
1840
1841
14
            if (Tok.isNot(tok::numeric_constant)) {
1842
3
              PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
1843
3
              return;
1844
3
            }
1845
1846
11
            Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
1847
11
            Alignment = Tok;
1848
1849
11
            PP.Lex(Tok);
1850
11
          }
1851
4
        } else {
1852
4
          PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
1853
4
          return;
1854
4
        }
1855
2.26k
      }
1856
326k
    }
1857
2.26k
  } else if (PP.getLangOpts().ApplePragmaPack ||
1858
2.26k
             PP.getLangOpts().XLPragmaPack) {
1859
    // In MSVC/gcc, #pragma pack() resets the alignment without affecting
1860
    // the push/pop stack.
1861
    // In Apple gcc and IBM XL, #pragma pack() is equivalent to #pragma
1862
    // pack(pop).
1863
11
    Action = Sema::PSK_Pop;
1864
11
  }
1865
1866
331k
  if (Tok.isNot(tok::r_paren)) {
1867
4
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
1868
4
    return;
1869
4
  }
1870
1871
331k
  SourceLocation RParenLoc = Tok.getLocation();
1872
331k
  PP.Lex(Tok);
1873
331k
  if (Tok.isNot(tok::eod)) {
1874
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
1875
0
    return;
1876
0
  }
1877
1878
331k
  PragmaPackInfo *Info =
1879
331k
      PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
1880
331k
  Info->Action = Action;
1881
331k
  Info->SlotLabel = SlotLabel;
1882
331k
  Info->Alignment = Alignment;
1883
1884
331k
  MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1885
331k
                              1);
1886
331k
  Toks[0].startToken();
1887
331k
  Toks[0].setKind(tok::annot_pragma_pack);
1888
331k
  Toks[0].setLocation(PackLoc);
1889
331k
  Toks[0].setAnnotationEndLoc(RParenLoc);
1890
331k
  Toks[0].setAnnotationValue(static_cast<void*>(Info));
1891
331k
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1892
331k
                      /*IsReinject=*/false);
1893
331k
}
1894
1895
// #pragma ms_struct on
1896
// #pragma ms_struct off
1897
void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
1898
                                         PragmaIntroducer Introducer,
1899
16
                                         Token &MSStructTok) {
1900
16
  PragmaMSStructKind Kind = PMSST_OFF;
1901
1902
16
  Token Tok;
1903
16
  PP.Lex(Tok);
1904
16
  if (Tok.isNot(tok::identifier)) {
1905
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1906
1
    return;
1907
1
  }
1908
15
  SourceLocation EndLoc = Tok.getLocation();
1909
15
  const IdentifierInfo *II = Tok.getIdentifierInfo();
1910
15
  if (II->isStr("on")) {
1911
11
    Kind = PMSST_ON;
1912
11
    PP.Lex(Tok);
1913
11
  }
1914
4
  else if (II->isStr("off") || 
II->isStr("reset")1
)
1915
4
    PP.Lex(Tok);
1916
0
  else {
1917
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1918
0
    return;
1919
0
  }
1920
1921
15
  if (Tok.isNot(tok::eod)) {
1922
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1923
1
      << "ms_struct";
1924
1
    return;
1925
1
  }
1926
1927
14
  MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1928
14
                              1);
1929
14
  Toks[0].startToken();
1930
14
  Toks[0].setKind(tok::annot_pragma_msstruct);
1931
14
  Toks[0].setLocation(MSStructTok.getLocation());
1932
14
  Toks[0].setAnnotationEndLoc(EndLoc);
1933
14
  Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1934
14
                             static_cast<uintptr_t>(Kind)));
1935
14
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1936
14
                      /*IsReinject=*/false);
1937
14
}
1938
1939
// #pragma clang section bss="abc" data="" rodata="def" text="" relro=""
1940
void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
1941
                                             PragmaIntroducer Introducer,
1942
52
                                             Token &FirstToken) {
1943
1944
52
  Token Tok;
1945
52
  auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;
1946
1947
52
  PP.Lex(Tok); // eat 'section'
1948
112
  while (Tok.isNot(tok::eod)) {
1949
71
    if (Tok.isNot(tok::identifier)) {
1950
0
      PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1951
0
      return;
1952
0
    }
1953
1954
71
    const IdentifierInfo *SecType = Tok.getIdentifierInfo();
1955
71
    if (SecType->isStr("bss"))
1956
17
      SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;
1957
54
    else if (SecType->isStr("data"))
1958
14
      SecKind = Sema::PragmaClangSectionKind::PCSK_Data;
1959
40
    else if (SecType->isStr("rodata"))
1960
16
      SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;
1961
24
    else if (SecType->isStr("relro"))
1962
2
      SecKind = Sema::PragmaClangSectionKind::PCSK_Relro;
1963
22
    else if (SecType->isStr("text"))
1964
16
      SecKind = Sema::PragmaClangSectionKind::PCSK_Text;
1965
6
    else {
1966
6
      PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1967
6
      return;
1968
6
    }
1969
1970
65
    SourceLocation PragmaLocation = Tok.getLocation();
1971
65
    PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
1972
65
    if (Tok.isNot(tok::equal)) {
1973
5
      PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
1974
5
      return;
1975
5
    }
1976
1977
60
    std::string SecName;
1978
60
    if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
1979
0
      return;
1980
1981
60
    Actions.ActOnPragmaClangSection(
1982
60
        PragmaLocation,
1983
34
        (SecName.size() ? Sema::PragmaClangSectionAction::PCSA_Set
1984
26
                        : Sema::PragmaClangSectionAction::PCSA_Clear),
1985
60
        SecKind, SecName);
1986
60
  }
1987
52
}
1988
1989
// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
1990
// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
1991
// #pragma 'align' '(' {'native','natural','mac68k','power','reset'} ')'
1992
static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
1993
3.64k
                             bool IsOptions) {
1994
3.64k
  Token Tok;
1995
1996
3.64k
  if (IsOptions) {
1997
3.57k
    PP.Lex(Tok);
1998
3.57k
    if (Tok.isNot(tok::identifier) ||
1999
3.57k
        !Tok.getIdentifierInfo()->isStr("align")) {
2000
1
      PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
2001
1
      return;
2002
1
    }
2003
3.64k
  }
2004
2005
3.64k
  PP.Lex(Tok);
2006
3.64k
  if (PP.getLangOpts().XLPragmaPack) {
2007
58
    if (Tok.isNot(tok::l_paren)) {
2008
2
      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "align";
2009
2
      return;
2010
2
    }
2011
3.58k
  } else if (Tok.isNot(tok::equal)) {
2012
2
    PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
2013
2
      << IsOptions;
2014
2
    return;
2015
2
  }
2016
2017
3.64k
  PP.Lex(Tok);
2018
3.64k
  if (Tok.isNot(tok::identifier)) {
2019
2
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2020
1
      << (IsOptions ? "options" : "align");
2021
2
    return;
2022
2
  }
2023
2024
3.63k
  Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
2025
3.63k
  const IdentifierInfo *II = Tok.getIdentifierInfo();
2026
3.63k
  if (II->isStr("native"))
2027
1
    Kind = Sema::POAK_Native;
2028
3.63k
  else if (II->isStr("natural"))
2029
29
    Kind = Sema::POAK_Natural;
2030
3.60k
  else if (II->isStr("packed"))
2031
11
    Kind = Sema::POAK_Packed;
2032
3.59k
  else if (II->isStr("power"))
2033
1.77k
    Kind = Sema::POAK_Power;
2034
1.82k
  else if (II->isStr("mac68k"))
2035
9
    Kind = Sema::POAK_Mac68k;
2036
1.81k
  else if (II->isStr("reset"))
2037
1.81k
    Kind = Sema::POAK_Reset;
2038
2
  else {
2039
2
    PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
2040
2
      << IsOptions;
2041
2
    return;
2042
2
  }
2043
2044
3.63k
  if (PP.getLangOpts().XLPragmaPack) {
2045
56
    PP.Lex(Tok);
2046
56
    if (Tok.isNot(tok::r_paren)) {
2047
0
      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "align";
2048
0
      return;
2049
0
    }
2050
3.63k
  }
2051
2052
3.63k
  SourceLocation EndLoc = Tok.getLocation();
2053
3.63k
  PP.Lex(Tok);
2054
3.63k
  if (Tok.isNot(tok::eod)) {
2055
2
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2056
1
      << (IsOptions ? "options" : "align");
2057
2
    return;
2058
2
  }
2059
2060
3.63k
  MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2061
3.63k
                              1);
2062
3.63k
  Toks[0].startToken();
2063
3.63k
  Toks[0].setKind(tok::annot_pragma_align);
2064
3.63k
  Toks[0].setLocation(FirstTok.getLocation());
2065
3.63k
  Toks[0].setAnnotationEndLoc(EndLoc);
2066
3.63k
  Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2067
3.63k
                             static_cast<uintptr_t>(Kind)));
2068
3.63k
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2069
3.63k
                      /*IsReinject=*/false);
2070
3.63k
}
2071
2072
void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
2073
                                      PragmaIntroducer Introducer,
2074
72
                                      Token &AlignTok) {
2075
72
  ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
2076
72
}
2077
2078
void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
2079
                                        PragmaIntroducer Introducer,
2080
3.57k
                                        Token &OptionsTok) {
2081
3.57k
  ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
2082
3.57k
}
2083
2084
// #pragma unused(identifier)
2085
void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
2086
                                       PragmaIntroducer Introducer,
2087
23
                                       Token &UnusedTok) {
2088
  // FIXME: Should we be expanding macros here? My guess is no.
2089
23
  SourceLocation UnusedLoc = UnusedTok.getLocation();
2090
2091
  // Lex the left '('.
2092
23
  Token Tok;
2093
23
  PP.Lex(Tok);
2094
23
  if (Tok.isNot(tok::l_paren)) {
2095
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
2096
1
    return;
2097
1
  }
2098
2099
  // Lex the declaration reference(s).
2100
22
  SmallVector<Token, 5> Identifiers;
2101
22
  SourceLocation RParenLoc;
2102
22
  bool LexID = true;
2103
2104
55
  while (true) {
2105
55
    PP.Lex(Tok);
2106
2107
55
    if (LexID) {
2108
29
      if (Tok.is(tok::identifier)) {
2109
26
        Identifiers.push_back(Tok);
2110
26
        LexID = false;
2111
26
        continue;
2112
26
      }
2113
2114
      // Illegal token!
2115
3
      PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
2116
3
      return;
2117
3
    }
2118
2119
    // We are execting a ')' or a ','.
2120
26
    if (Tok.is(tok::comma)) {
2121
7
      LexID = true;
2122
7
      continue;
2123
7
    }
2124
2125
19
    if (Tok.is(tok::r_paren)) {
2126
19
      RParenLoc = Tok.getLocation();
2127
19
      break;
2128
19
    }
2129
2130
    // Illegal token!
2131
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
2132
0
    return;
2133
0
  }
2134
2135
19
  PP.Lex(Tok);
2136
19
  if (Tok.isNot(tok::eod)) {
2137
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2138
0
        "unused";
2139
0
    return;
2140
0
  }
2141
2142
  // Verify that we have a location for the right parenthesis.
2143
19
  assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
2144
19
  assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
2145
2146
  // For each identifier token, insert into the token stream a
2147
  // annot_pragma_unused token followed by the identifier token.
2148
  // This allows us to cache a "#pragma unused" that occurs inside an inline
2149
  // C++ member function.
2150
2151
19
  MutableArrayRef<Token> Toks(
2152
19
      PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
2153
19
      2 * Identifiers.size());
2154
44
  for (unsigned i=0; i != Identifiers.size(); 
i++25
) {
2155
25
    Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
2156
25
    pragmaUnusedTok.startToken();
2157
25
    pragmaUnusedTok.setKind(tok::annot_pragma_unused);
2158
25
    pragmaUnusedTok.setLocation(UnusedLoc);
2159
25
    idTok = Identifiers[i];
2160
25
  }
2161
19
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2162
19
                      /*IsReinject=*/false);
2163
19
}
2164
2165
// #pragma weak identifier
2166
// #pragma weak identifier '=' identifier
2167
void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
2168
                                     PragmaIntroducer Introducer,
2169
119
                                     Token &WeakTok) {
2170
119
  SourceLocation WeakLoc = WeakTok.getLocation();
2171
2172
119
  Token Tok;
2173
119
  PP.Lex(Tok);
2174
119
  if (Tok.isNot(tok::identifier)) {
2175
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
2176
1
    return;
2177
1
  }
2178
2179
118
  Token WeakName = Tok;
2180
118
  bool HasAlias = false;
2181
118
  Token AliasName;
2182
2183
118
  PP.Lex(Tok);
2184
118
  if (Tok.is(tok::equal)) {
2185
25
    HasAlias = true;
2186
25
    PP.Lex(Tok);
2187
25
    if (Tok.isNot(tok::identifier)) {
2188
2
      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2189
2
          << "weak";
2190
2
      return;
2191
2
    }
2192
23
    AliasName = Tok;
2193
23
    PP.Lex(Tok);
2194
23
  }
2195
2196
116
  if (Tok.isNot(tok::eod)) {
2197
2
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
2198
2
    return;
2199
2
  }
2200
2201
114
  if (HasAlias) {
2202
22
    MutableArrayRef<Token> Toks(
2203
22
        PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
2204
22
    Token &pragmaUnusedTok = Toks[0];
2205
22
    pragmaUnusedTok.startToken();
2206
22
    pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
2207
22
    pragmaUnusedTok.setLocation(WeakLoc);
2208
22
    pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
2209
22
    Toks[1] = WeakName;
2210
22
    Toks[2] = AliasName;
2211
22
    PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2212
22
                        /*IsReinject=*/false);
2213
92
  } else {
2214
92
    MutableArrayRef<Token> Toks(
2215
92
        PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
2216
92
    Token &pragmaUnusedTok = Toks[0];
2217
92
    pragmaUnusedTok.startToken();
2218
92
    pragmaUnusedTok.setKind(tok::annot_pragma_weak);
2219
92
    pragmaUnusedTok.setLocation(WeakLoc);
2220
92
    pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
2221
92
    Toks[1] = WeakName;
2222
92
    PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2223
92
                        /*IsReinject=*/false);
2224
92
  }
2225
114
}
2226
2227
// #pragma redefine_extname identifier identifier
2228
void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
2229
                                                PragmaIntroducer Introducer,
2230
10
                                                Token &RedefToken) {
2231
10
  SourceLocation RedefLoc = RedefToken.getLocation();
2232
2233
10
  Token Tok;
2234
10
  PP.Lex(Tok);
2235
10
  if (Tok.isNot(tok::identifier)) {
2236
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2237
0
      "redefine_extname";
2238
0
    return;
2239
0
  }
2240
2241
10
  Token RedefName = Tok;
2242
10
  PP.Lex(Tok);
2243
2244
10
  if (Tok.isNot(tok::identifier)) {
2245
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2246
0
        << "redefine_extname";
2247
0
    return;
2248
0
  }
2249
2250
10
  Token AliasName = Tok;
2251
10
  PP.Lex(Tok);
2252
2253
10
  if (Tok.isNot(tok::eod)) {
2254
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2255
0
      "redefine_extname";
2256
0
    return;
2257
0
  }
2258
2259
10
  MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),
2260
10
                              3);
2261
10
  Token &pragmaRedefTok = Toks[0];
2262
10
  pragmaRedefTok.startToken();
2263
10
  pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
2264
10
  pragmaRedefTok.setLocation(RedefLoc);
2265
10
  pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
2266
10
  Toks[1] = RedefName;
2267
10
  Toks[2] = AliasName;
2268
10
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2269
10
                      /*IsReinject=*/false);
2270
10
}
2271
2272
void PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
2273
                                           PragmaIntroducer Introducer,
2274
43
                                           Token &Tok) {
2275
43
  tok::OnOffSwitch OOS;
2276
43
  if (PP.LexOnOffSwitch(OOS))
2277
2
    return;
2278
2279
41
  MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2280
41
                              1);
2281
41
  Toks[0].startToken();
2282
41
  Toks[0].setKind(tok::annot_pragma_fp_contract);
2283
41
  Toks[0].setLocation(Tok.getLocation());
2284
41
  Toks[0].setAnnotationEndLoc(Tok.getLocation());
2285
41
  Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2286
41
                             static_cast<uintptr_t>(OOS)));
2287
41
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2288
41
                      /*IsReinject=*/false);
2289
41
}
2290
2291
void PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
2292
                                                PragmaIntroducer Introducer,
2293
1.72k
                                                Token &Tok) {
2294
1.72k
  PP.LexUnexpandedToken(Tok);
2295
1.72k
  if (Tok.isNot(tok::identifier)) {
2296
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2297
0
      "OPENCL";
2298
0
    return;
2299
0
  }
2300
1.72k
  IdentifierInfo *Ext = Tok.getIdentifierInfo();
2301
1.72k
  SourceLocation NameLoc = Tok.getLocation();
2302
2303
1.72k
  PP.Lex(Tok);
2304
1.72k
  if (Tok.isNot(tok::colon)) {
2305
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
2306
0
    return;
2307
0
  }
2308
2309
1.72k
  PP.Lex(Tok);
2310
1.72k
  if (Tok.isNot(tok::identifier)) {
2311
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
2312
0
    return;
2313
0
  }
2314
1.72k
  IdentifierInfo *Pred = Tok.getIdentifierInfo();
2315
2316
1.72k
  OpenCLExtState State;
2317
1.72k
  if (Pred->isStr("enable")) {
2318
1.39k
    State = Enable;
2319
322
  } else if (Pred->isStr("disable")) {
2320
137
    State = Disable;
2321
185
  } else if (Pred->isStr("begin"))
2322
90
    State = Begin;
2323
95
  else if (Pred->isStr("end"))
2324
94
    State = End;
2325
1
  else {
2326
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
2327
1
      << Ext->isStr("all");
2328
1
    return;
2329
1
  }
2330
1.72k
  SourceLocation StateLoc = Tok.getLocation();
2331
2332
1.72k
  PP.Lex(Tok);
2333
1.72k
  if (Tok.isNot(tok::eod)) {
2334
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2335
0
      "OPENCL EXTENSION";
2336
0
    return;
2337
0
  }
2338
2339
1.72k
  auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
2340
1.72k
  Info->first = Ext;
2341
1.72k
  Info->second = State;
2342
1.72k
  MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2343
1.72k
                              1);
2344
1.72k
  Toks[0].startToken();
2345
1.72k
  Toks[0].setKind(tok::annot_pragma_opencl_extension);
2346
1.72k
  Toks[0].setLocation(NameLoc);
2347
1.72k
  Toks[0].setAnnotationValue(static_cast<void*>(Info));
2348
1.72k
  Toks[0].setAnnotationEndLoc(StateLoc);
2349
1.72k
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2350
1.72k
                      /*IsReinject=*/false);
2351
2352
1.72k
  if (PP.getPPCallbacks())
2353
1.72k
    PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
2354
1.72k
                                               StateLoc, State);
2355
1.72k
}
2356
2357
/// Handle '#pragma omp ...' when OpenMP is disabled.
2358
///
2359
void PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
2360
                                         PragmaIntroducer Introducer,
2361
95
                                         Token &FirstTok) {
2362
95
  if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
2363
2
                                     FirstTok.getLocation())) {
2364
2
    PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
2365
2
    PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
2366
2
                                    diag::Severity::Ignored, SourceLocation());
2367
2
  }
2368
95
  PP.DiscardUntilEndOfDirective();
2369
95
}
2370
2371
/// Handle '#pragma omp ...' when OpenMP is enabled.
2372
///
2373
void PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
2374
                                       PragmaIntroducer Introducer,
2375
232k
                                       Token &FirstTok) {
2376
232k
  SmallVector<Token, 16> Pragma;
2377
232k
  Token Tok;
2378
232k
  Tok.startToken();
2379
232k
  Tok.setKind(tok::annot_pragma_openmp);
2380
232k
  Tok.setLocation(Introducer.Loc);
2381
2382
1.92M
  while (Tok.isNot(tok::eod) && 
Tok.isNot(tok::eof)1.68M
) {
2383
1.68M
    Pragma.push_back(Tok);
2384
1.68M
    PP.Lex(Tok);
2385
1.68M
    if (Tok.is(tok::annot_pragma_openmp)) {
2386
6
      PP.Diag(Tok, diag::err_omp_unexpected_directive) << 0;
2387
6
      unsigned InnerPragmaCnt = 1;
2388
18
      while (InnerPragmaCnt != 0) {
2389
12
        PP.Lex(Tok);
2390
12
        if (Tok.is(tok::annot_pragma_openmp))
2391
0
          ++InnerPragmaCnt;
2392
12
        else if (Tok.is(tok::annot_pragma_openmp_end))
2393
6
          --InnerPragmaCnt;
2394
12
      }
2395
6
      PP.Lex(Tok);
2396
6
    }
2397
1.68M
  }
2398
232k
  SourceLocation EodLoc = Tok.getLocation();
2399
232k
  Tok.startToken();
2400
232k
  Tok.setKind(tok::annot_pragma_openmp_end);
2401
232k
  Tok.setLocation(EodLoc);
2402
232k
  Pragma.push_back(Tok);
2403
2404
232k
  auto Toks = std::make_unique<Token[]>(Pragma.size());
2405
232k
  std::copy(Pragma.begin(), Pragma.end(), Toks.get());
2406
232k
  PP.EnterTokenStream(std::move(Toks), Pragma.size(),
2407
232k
                      /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
2408
232k
}
2409
2410
/// Handle '#pragma pointers_to_members'
2411
// The grammar for this pragma is as follows:
2412
//
2413
// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
2414
//
2415
// #pragma pointers_to_members '(' 'best_case' ')'
2416
// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
2417
// #pragma pointers_to_members '(' inheritance-model ')'
2418
void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
2419
                                             PragmaIntroducer Introducer,
2420
27
                                             Token &Tok) {
2421
27
  SourceLocation PointersToMembersLoc = Tok.getLocation();
2422
27
  PP.Lex(Tok);
2423
27
  if (Tok.isNot(tok::l_paren)) {
2424
0
    PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
2425
0
      << "pointers_to_members";
2426
0
    return;
2427
0
  }
2428
27
  PP.Lex(Tok);
2429
27
  const IdentifierInfo *Arg = Tok.getIdentifierInfo();
2430
27
  if (!Arg) {
2431
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2432
0
      << "pointers_to_members";
2433
0
    return;
2434
0
  }
2435
27
  PP.Lex(Tok);
2436
2437
27
  LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
2438
27
  if (Arg->isStr("best_case")) {
2439
10
    RepresentationMethod = LangOptions::PPTMK_BestCase;
2440
17
  } else {
2441
17
    if (Arg->isStr("full_generality")) {
2442
13
      if (Tok.is(tok::comma)) {
2443
13
        PP.Lex(Tok);
2444
2445
13
        Arg = Tok.getIdentifierInfo();
2446
13
        if (!Arg) {
2447
0
          PP.Diag(Tok.getLocation(),
2448
0
                  diag::err_pragma_pointers_to_members_unknown_kind)
2449
0
              << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
2450
0
          return;
2451
0
        }
2452
13
        PP.Lex(Tok);
2453
0
      } else if (Tok.is(tok::r_paren)) {
2454
        // #pragma pointers_to_members(full_generality) implicitly specifies
2455
        // virtual_inheritance.
2456
0
        Arg = nullptr;
2457
0
        RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
2458
0
      } else {
2459
0
        PP.Diag(Tok.getLocation(), diag::err_expected_punc)
2460
0
            << "full_generality";
2461
0
        return;
2462
0
      }
2463
17
    }
2464
2465
17
    if (Arg) {
2466
17
      if (Arg->isStr("single_inheritance")) {
2467
2
        RepresentationMethod =
2468
2
            LangOptions::PPTMK_FullGeneralitySingleInheritance;
2469
15
      } else if (Arg->isStr("multiple_inheritance")) {
2470
2
        RepresentationMethod =
2471
2
            LangOptions::PPTMK_FullGeneralityMultipleInheritance;
2472
13
      } else if (Arg->isStr("virtual_inheritance")) {
2473
11
        RepresentationMethod =
2474
11
            LangOptions::PPTMK_FullGeneralityVirtualInheritance;
2475
2
      } else {
2476
2
        PP.Diag(Tok.getLocation(),
2477
2
                diag::err_pragma_pointers_to_members_unknown_kind)
2478
2
            << Arg << /*HasPointerDeclaration*/ 1;
2479
2
        return;
2480
2
      }
2481
25
    }
2482
17
  }
2483
2484
25
  if (Tok.isNot(tok::r_paren)) {
2485
0
    PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
2486
0
        << (Arg ? Arg->getName() : "full_generality");
2487
0
    return;
2488
0
  }
2489
2490
25
  SourceLocation EndLoc = Tok.getLocation();
2491
25
  PP.Lex(Tok);
2492
25
  if (Tok.isNot(tok::eod)) {
2493
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2494
0
      << "pointers_to_members";
2495
0
    return;
2496
0
  }
2497
2498
25
  Token AnnotTok;
2499
25
  AnnotTok.startToken();
2500
25
  AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
2501
25
  AnnotTok.setLocation(PointersToMembersLoc);
2502
25
  AnnotTok.setAnnotationEndLoc(EndLoc);
2503
25
  AnnotTok.setAnnotationValue(
2504
25
      reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
2505
25
  PP.EnterToken(AnnotTok, /*IsReinject=*/true);
2506
25
}
2507
2508
/// Handle '#pragma vtordisp'
2509
// The grammar for this pragma is as follows:
2510
//
2511
// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
2512
//
2513
// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
2514
// #pragma vtordisp '(' 'pop' ')'
2515
// #pragma vtordisp '(' ')'
2516
void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
2517
52
                                    PragmaIntroducer Introducer, Token &Tok) {
2518
52
  SourceLocation VtorDispLoc = Tok.getLocation();
2519
52
  PP.Lex(Tok);
2520
52
  if (Tok.isNot(tok::l_paren)) {
2521
1
    PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
2522
1
    return;
2523
1
  }
2524
51
  PP.Lex(Tok);
2525
2526
51
  Sema::PragmaMsStackAction Action = Sema::PSK_Set;
2527
51
  const IdentifierInfo *II = Tok.getIdentifierInfo();
2528
51
  if (II) {
2529
41
    if (II->isStr("push")) {
2530
      // #pragma vtordisp(push, mode)
2531
20
      PP.Lex(Tok);
2532
20
      if (Tok.isNot(tok::comma)) {
2533
0
        PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
2534
0
        return;
2535
0
      }
2536
20
      PP.Lex(Tok);
2537
20
      Action = Sema::PSK_Push_Set;
2538
      // not push, could be on/off
2539
21
    } else if (II->isStr("pop")) {
2540
      // #pragma vtordisp(pop)
2541
20
      PP.Lex(Tok);
2542
20
      Action = Sema::PSK_Pop;
2543
20
    }
2544
    // not push or pop, could be on/off
2545
10
  } else {
2546
10
    if (Tok.is(tok::r_paren)) {
2547
      // #pragma vtordisp()
2548
4
      Action = Sema::PSK_Reset;
2549
4
    }
2550
10
  }
2551
2552
2553
51
  uint64_t Value = 0;
2554
51
  if (Action & Sema::PSK_Push || 
Action & Sema::PSK_Set31
) {
2555
27
    const IdentifierInfo *II = Tok.getIdentifierInfo();
2556
27
    if (II && 
II->isStr("off")1
) {
2557
0
      PP.Lex(Tok);
2558
0
      Value = 0;
2559
27
    } else if (II && 
II->isStr("on")1
) {
2560
0
      PP.Lex(Tok);
2561
0
      Value = 1;
2562
27
    } else if (Tok.is(tok::numeric_constant) &&
2563
24
               PP.parseSimpleIntegerLiteral(Tok, Value)) {
2564
24
      if (Value > 2) {
2565
2
        PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
2566
2
            << 0 << 2 << "vtordisp";
2567
2
        return;
2568
2
      }
2569
3
    } else {
2570
3
      PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
2571
3
          << "vtordisp";
2572
3
      return;
2573
3
    }
2574
46
  }
2575
2576
  // Finish the pragma: ')' $
2577
46
  if (Tok.isNot(tok::r_paren)) {
2578
0
    PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
2579
0
    return;
2580
0
  }
2581
46
  SourceLocation EndLoc = Tok.getLocation();
2582
46
  PP.Lex(Tok);
2583
46
  if (Tok.isNot(tok::eod)) {
2584
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2585
1
        << "vtordisp";
2586
1
    return;
2587
1
  }
2588
2589
  // Enter the annotation.
2590
45
  Token AnnotTok;
2591
45
  AnnotTok.startToken();
2592
45
  AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
2593
45
  AnnotTok.setLocation(VtorDispLoc);
2594
45
  AnnotTok.setAnnotationEndLoc(EndLoc);
2595
45
  AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
2596
45
      static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
2597
45
  PP.EnterToken(AnnotTok, /*IsReinject=*/false);
2598
45
}
2599
2600
/// Handle all MS pragmas.  Simply forwards the tokens after inserting
2601
/// an annotation token.
2602
void PragmaMSPragma::HandlePragma(Preprocessor &PP,
2603
146
                                  PragmaIntroducer Introducer, Token &Tok) {
2604
146
  Token EoF, AnnotTok;
2605
146
  EoF.startToken();
2606
146
  EoF.setKind(tok::eof);
2607
146
  AnnotTok.startToken();
2608
146
  AnnotTok.setKind(tok::annot_pragma_ms_pragma);
2609
146
  AnnotTok.setLocation(Tok.getLocation());
2610
146
  AnnotTok.setAnnotationEndLoc(Tok.getLocation());
2611
146
  SmallVector<Token, 8> TokenVector;
2612
  // Suck up all of the tokens before the eod.
2613
874
  for (; Tok.isNot(tok::eod); 
PP.Lex(Tok)728
) {
2614
728
    TokenVector.push_back(Tok);
2615
728
    AnnotTok.setAnnotationEndLoc(Tok.getLocation());
2616
728
  }
2617
  // Add a sentinel EoF token to the end of the list.
2618
146
  TokenVector.push_back(EoF);
2619
  // We must allocate this array with new because EnterTokenStream is going to
2620
  // delete it later.
2621
146
  auto TokenArray = std::make_unique<Token[]>(TokenVector.size());
2622
146
  std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
2623
146
  auto Value = new (PP.getPreprocessorAllocator())
2624
146
      std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
2625
146
                                                  TokenVector.size());
2626
146
  AnnotTok.setAnnotationValue(Value);
2627
146
  PP.EnterToken(AnnotTok, /*IsReinject*/ false);
2628
146
}
2629
2630
/// Handle the \#pragma float_control extension.
2631
///
2632
/// The syntax is:
2633
/// \code
2634
///   #pragma float_control(keyword[, setting] [,push])
2635
/// \endcode
2636
/// Where 'keyword' and 'setting' are identifiers.
2637
// 'keyword' can be: precise, except, push, pop
2638
// 'setting' can be: on, off
2639
/// The optional arguments 'setting' and 'push' are supported only
2640
/// when the keyword is 'precise' or 'except'.
2641
void PragmaFloatControlHandler::HandlePragma(Preprocessor &PP,
2642
                                             PragmaIntroducer Introducer,
2643
259
                                             Token &Tok) {
2644
259
  Sema::PragmaMsStackAction Action = Sema::PSK_Set;
2645
259
  SourceLocation FloatControlLoc = Tok.getLocation();
2646
259
  Token PragmaName = Tok;
2647
259
  if (!PP.getTargetInfo().hasStrictFP() && 
!PP.getLangOpts().ExpStrictFP11
) {
2648
3
    PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
2649
3
        << PragmaName.getIdentifierInfo()->getName();
2650
3
    return;
2651
3
  }
2652
256
  PP.Lex(Tok);
2653
256
  if (Tok.isNot(tok::l_paren)) {
2654
0
    PP.Diag(FloatControlLoc, diag::err_expected) << tok::l_paren;
2655
0
    return;
2656
0
  }
2657
2658
  // Read the identifier.
2659
256
  PP.Lex(Tok);
2660
256
  if (Tok.isNot(tok::identifier)) {
2661
0
    PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2662
0
    return;
2663
0
  }
2664
2665
  // Verify that this is one of the float control options.
2666
256
  IdentifierInfo *II = Tok.getIdentifierInfo();
2667
256
  PragmaFloatControlKind Kind =
2668
256
      llvm::StringSwitch<PragmaFloatControlKind>(II->getName())
2669
256
          .Case("precise", PFC_Precise)
2670
256
          .Case("except", PFC_Except)
2671
256
          .Case("push", PFC_Push)
2672
256
          .Case("pop", PFC_Pop)
2673
256
          .Default(PFC_Unknown);
2674
256
  PP.Lex(Tok); // the identifier
2675
256
  if (Kind == PFC_Unknown) {
2676
0
    PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2677
0
    return;
2678
256
  } else if (Kind == PFC_Push || 
Kind == PFC_Pop230
) {
2679
80
    if (Tok.isNot(tok::r_paren)) {
2680
0
      PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2681
0
      return;
2682
0
    }
2683
80
    PP.Lex(Tok); // Eat the r_paren
2684
54
    Action = (Kind == PFC_Pop) ? Sema::PSK_Pop : 
Sema::PSK_Push26
;
2685
176
  } else {
2686
176
    if (Tok.is(tok::r_paren))
2687
      // Selecting Precise or Except
2688
0
      PP.Lex(Tok); // the r_paren
2689
176
    else if (Tok.isNot(tok::comma)) {
2690
0
      PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2691
0
      return;
2692
176
    } else {
2693
176
      PP.Lex(Tok); // ,
2694
176
      if (!Tok.isAnyIdentifier()) {
2695
0
        PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2696
0
        return;
2697
0
      }
2698
176
      StringRef PushOnOff = Tok.getIdentifierInfo()->getName();
2699
176
      if (PushOnOff == "on")
2700
        // Kind is set correctly
2701
106
        ;
2702
70
      else if (PushOnOff == "off") {
2703
70
        if (Kind == PFC_Precise)
2704
53
          Kind = PFC_NoPrecise;
2705
70
        if (Kind == PFC_Except)
2706
17
          Kind = PFC_NoExcept;
2707
0
      } else if (PushOnOff == "push") {
2708
0
        Action = Sema::PSK_Push_Set;
2709
0
      } else {
2710
0
        PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2711
0
        return;
2712
0
      }
2713
176
      PP.Lex(Tok); // the identifier
2714
176
      if (Tok.is(tok::comma)) {
2715
12
        PP.Lex(Tok); // ,
2716
12
        if (!Tok.isAnyIdentifier()) {
2717
0
          PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2718
0
          return;
2719
0
        }
2720
12
        StringRef ExpectedPush = Tok.getIdentifierInfo()->getName();
2721
12
        if (ExpectedPush == "push") {
2722
12
          Action = Sema::PSK_Push_Set;
2723
0
        } else {
2724
0
          PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2725
0
          return;
2726
0
        }
2727
12
        PP.Lex(Tok); // the push identifier
2728
12
      }
2729
176
      if (Tok.isNot(tok::r_paren)) {
2730
1
        PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2731
1
        return;
2732
1
      }
2733
175
      PP.Lex(Tok); // the r_paren
2734
175
    }
2735
176
  }
2736
255
  SourceLocation EndLoc = Tok.getLocation();
2737
255
  if (Tok.isNot(tok::eod)) {
2738
5
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2739
5
        << "float_control";
2740
5
    return;
2741
5
  }
2742
2743
  // Note: there is no accomodation for PP callback for this pragma.
2744
2745
  // Enter the annotation.
2746
250
  auto TokenArray = std::make_unique<Token[]>(1);
2747
250
  TokenArray[0].startToken();
2748
250
  TokenArray[0].setKind(tok::annot_pragma_float_control);
2749
250
  TokenArray[0].setLocation(FloatControlLoc);
2750
250
  TokenArray[0].setAnnotationEndLoc(EndLoc);
2751
  // Create an encoding of Action and Value by shifting the Action into
2752
  // the high 16 bits then union with the Kind.
2753
250
  TokenArray[0].setAnnotationValue(reinterpret_cast<void *>(
2754
250
      static_cast<uintptr_t>((Action << 16) | (Kind & 0xFFFF))));
2755
250
  PP.EnterTokenStream(std::move(TokenArray), 1,
2756
250
                      /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
2757
250
}
2758
2759
/// Handle the Microsoft \#pragma detect_mismatch extension.
2760
///
2761
/// The syntax is:
2762
/// \code
2763
///   #pragma detect_mismatch("name", "value")
2764
/// \endcode
2765
/// Where 'name' and 'value' are quoted strings.  The values are embedded in
2766
/// the object file and passed along to the linker.  If the linker detects a
2767
/// mismatch in the object file's values for the given name, a LNK2038 error
2768
/// is emitted.  See MSDN for more details.
2769
void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
2770
                                               PragmaIntroducer Introducer,
2771
19
                                               Token &Tok) {
2772
19
  SourceLocation DetectMismatchLoc = Tok.getLocation();
2773
19
  PP.Lex(Tok);
2774
19
  if (Tok.isNot(tok::l_paren)) {
2775
0
    PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
2776
0
    return;
2777
0
  }
2778
2779
  // Read the name to embed, which must be a string literal.
2780
19
  std::string NameString;
2781
19
  if (!PP.LexStringLiteral(Tok, NameString,
2782
19
                           "pragma detect_mismatch",
2783
19
                           /*AllowMacroExpansion=*/true))
2784
1
    return;
2785
2786
  // Read the comma followed by a second string literal.
2787
18
  std::string ValueString;
2788
18
  if (Tok.isNot(tok::comma)) {
2789
1
    PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2790
1
    return;
2791
1
  }
2792
2793
17
  if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
2794
17
                           /*AllowMacroExpansion=*/true))
2795
1
    return;
2796
2797
16
  if (Tok.isNot(tok::r_paren)) {
2798
0
    PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2799
0
    return;
2800
0
  }
2801
16
  PP.Lex(Tok);  // Eat the r_paren.
2802
2803
16
  if (Tok.isNot(tok::eod)) {
2804
0
    PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2805
0
    return;
2806
0
  }
2807
2808
  // If the pragma is lexically sound, notify any interested PPCallbacks.
2809
16
  if (PP.getPPCallbacks())
2810
16
    PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
2811
16
                                              ValueString);
2812
2813
16
  Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
2814
16
}
2815
2816
/// Handle the microsoft \#pragma comment extension.
2817
///
2818
/// The syntax is:
2819
/// \code
2820
///   #pragma comment(linker, "foo")
2821
/// \endcode
2822
/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
2823
/// "foo" is a string, which is fully macro expanded, and permits string
2824
/// concatenation, embedded escape characters etc.  See MSDN for more details.
2825
void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
2826
                                        PragmaIntroducer Introducer,
2827
81
                                        Token &Tok) {
2828
81
  SourceLocation CommentLoc = Tok.getLocation();
2829
81
  PP.Lex(Tok);
2830
81
  if (Tok.isNot(tok::l_paren)) {
2831
0
    PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2832
0
    return;
2833
0
  }
2834
2835
  // Read the identifier.
2836
81
  PP.Lex(Tok);
2837
81
  if (Tok.isNot(tok::identifier)) {
2838
0
    PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2839
0
    return;
2840
0
  }
2841
2842
  // Verify that this is one of the 5 explicitly listed options.
2843
81
  IdentifierInfo *II = Tok.getIdentifierInfo();
2844
81
  PragmaMSCommentKind Kind =
2845
81
    llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
2846
81
    .Case("linker",   PCK_Linker)
2847
81
    .Case("lib",      PCK_Lib)
2848
81
    .Case("compiler", PCK_Compiler)
2849
81
    .Case("exestr",   PCK_ExeStr)
2850
81
    .Case("user",     PCK_User)
2851
81
    .Default(PCK_Unknown);
2852
81
  if (Kind == PCK_Unknown) {
2853
3
    PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
2854
3
    return;
2855
3
  }
2856
2857
78
  if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && 
Kind != PCK_Lib38
) {
2858
19
    PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
2859
19
        << II->getName();
2860
19
    return;
2861
19
  }
2862
2863
  // On PS4, issue a warning about any pragma comments other than
2864
  // #pragma comment lib.
2865
59
  if (PP.getTargetInfo().getTriple().isPS4() && 
Kind != PCK_Lib7
) {
2866
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
2867
0
      << II->getName();
2868
0
    return;
2869
0
  }
2870
2871
  // Read the optional string if present.
2872
59
  PP.Lex(Tok);
2873
59
  std::string ArgumentString;
2874
59
  if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
2875
56
                                                 "pragma comment",
2876
56
                                                 /*AllowMacroExpansion=*/true))
2877
1
    return;
2878
2879
  // FIXME: warn that 'exestr' is deprecated.
2880
  // FIXME: If the kind is "compiler" warn if the string is present (it is
2881
  // ignored).
2882
  // The MSDN docs say that "lib" and "linker" require a string and have a short
2883
  // list of linker options they support, but in practice MSVC doesn't
2884
  // issue a diagnostic.  Therefore neither does clang.
2885
2886
58
  if (Tok.isNot(tok::r_paren)) {
2887
1
    PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2888
1
    return;
2889
1
  }
2890
57
  PP.Lex(Tok);  // eat the r_paren.
2891
2892
57
  if (Tok.isNot(tok::eod)) {
2893
1
    PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2894
1
    return;
2895
1
  }
2896
2897
  // If the pragma is lexically sound, notify any interested PPCallbacks.
2898
56
  if (PP.getPPCallbacks())
2899
56
    PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
2900
2901
56
  Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
2902
56
}
2903
2904
// #pragma clang optimize off
2905
// #pragma clang optimize on
2906
void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
2907
                                         PragmaIntroducer Introducer,
2908
33
                                         Token &FirstToken) {
2909
33
  Token Tok;
2910
33
  PP.Lex(Tok);
2911
33
  if (Tok.is(tok::eod)) {
2912
1
    PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
2913
1
        << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
2914
1
    return;
2915
1
  }
2916
32
  if (Tok.isNot(tok::identifier)) {
2917
0
    PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2918
0
      << PP.getSpelling(Tok);
2919
0
    return;
2920
0
  }
2921
32
  const IdentifierInfo *II = Tok.getIdentifierInfo();
2922
  // The only accepted values are 'on' or 'off'.
2923
32
  bool IsOn = false;
2924
32
  if (II->isStr("on")) {
2925
15
    IsOn = true;
2926
17
  } else if (!II->isStr("off")) {
2927
1
    PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2928
1
      << PP.getSpelling(Tok);
2929
1
    return;
2930
1
  }
2931
31
  PP.Lex(Tok);
2932
2933
31
  if (Tok.isNot(tok::eod)) {
2934
1
    PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
2935
1
      << PP.getSpelling(Tok);
2936
1
    return;
2937
1
  }
2938
2939
30
  Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
2940
30
}
2941
2942
namespace {
2943
/// Used as the annotation value for tok::annot_pragma_fp.
2944
struct TokFPAnnotValue {
2945
  enum FlagKinds { Contract, Reassociate, Exceptions };
2946
  enum FlagValues { On, Off, Fast };
2947
2948
  llvm::Optional<LangOptions::FPModeKind> ContractValue;
2949
  llvm::Optional<LangOptions::FPModeKind> ReassociateValue;
2950
  llvm::Optional<LangOptions::FPExceptionModeKind> ExceptionsValue;
2951
};
2952
} // end anonymous namespace
2953
2954
void PragmaFPHandler::HandlePragma(Preprocessor &PP,
2955
62
                                   PragmaIntroducer Introducer, Token &Tok) {
2956
  // fp
2957
62
  Token PragmaName = Tok;
2958
62
  SmallVector<Token, 1> TokenList;
2959
2960
62
  PP.Lex(Tok);
2961
62
  if (Tok.isNot(tok::identifier)) {
2962
1
    PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2963
1
        << /*MissingOption=*/true << "";
2964
1
    return;
2965
1
  }
2966
2967
61
  auto *AnnotValue = new (PP.getPreprocessorAllocator()) TokFPAnnotValue;
2968
119
  while (Tok.is(tok::identifier)) {
2969
65
    IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2970
2971
65
    auto FlagKind =
2972
65
        llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagKinds>>(
2973
65
            OptionInfo->getName())
2974
65
            .Case("contract", TokFPAnnotValue::Contract)
2975
65
            .Case("reassociate", TokFPAnnotValue::Reassociate)
2976
65
            .Case("exceptions", TokFPAnnotValue::Exceptions)
2977
65
            .Default(None);
2978
65
    if (!FlagKind) {
2979
1
      PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2980
1
          << /*MissingOption=*/false << OptionInfo;
2981
1
      return;
2982
1
    }
2983
64
    PP.Lex(Tok);
2984
2985
    // Read '('
2986
64
    if (Tok.isNot(tok::l_paren)) {
2987
1
      PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
2988
1
      return;
2989
1
    }
2990
63
    PP.Lex(Tok);
2991
2992
63
    if (Tok.isNot(tok::identifier)) {
2993
1
      PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
2994
1
          << PP.getSpelling(Tok) << OptionInfo->getName()
2995
1
          << static_cast<int>(*FlagKind);
2996
1
      return;
2997
1
    }
2998
62
    const IdentifierInfo *II = Tok.getIdentifierInfo();
2999
3000
62
    if (FlagKind == TokFPAnnotValue::Contract) {
3001
45
      AnnotValue->ContractValue =
3002
45
          llvm::StringSwitch<llvm::Optional<LangOptions::FPModeKind>>(
3003
45
              II->getName())
3004
45
              .Case("on", LangOptions::FPModeKind::FPM_On)
3005
45
              .Case("off", LangOptions::FPModeKind::FPM_Off)
3006
45
              .Case("fast", LangOptions::FPModeKind::FPM_Fast)
3007
45
              .Default(llvm::None);
3008
45
      if (!AnnotValue->ContractValue) {
3009
1
        PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3010
1
            << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3011
1
        return;
3012
1
      }
3013
17
    } else if (FlagKind == TokFPAnnotValue::Reassociate) {
3014
13
      AnnotValue->ReassociateValue =
3015
13
          llvm::StringSwitch<llvm::Optional<LangOptions::FPModeKind>>(
3016
13
              II->getName())
3017
13
              .Case("on", LangOptions::FPModeKind::FPM_On)
3018
13
              .Case("off", LangOptions::FPModeKind::FPM_Off)
3019
13
              .Default(llvm::None);
3020
13
      if (!AnnotValue->ReassociateValue) {
3021
1
        PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3022
1
            << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3023
1
        return;
3024
1
      }
3025
4
    } else if (FlagKind == TokFPAnnotValue::Exceptions) {
3026
4
      AnnotValue->ExceptionsValue =
3027
4
          llvm::StringSwitch<llvm::Optional<LangOptions::FPExceptionModeKind>>(
3028
4
              II->getName())
3029
4
              .Case("ignore", LangOptions::FPE_Ignore)
3030
4
              .Case("maytrap", LangOptions::FPE_MayTrap)
3031
4
              .Case("strict", LangOptions::FPE_Strict)
3032
4
              .Default(llvm::None);
3033
4
      if (!AnnotValue->ExceptionsValue) {
3034
1
        PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3035
1
            << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3036
1
        return;
3037
1
      }
3038
59
    }
3039
59
    PP.Lex(Tok);
3040
3041
    // Read ')'
3042
59
    if (Tok.isNot(tok::r_paren)) {
3043
1
      PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3044
1
      return;
3045
1
    }
3046
58
    PP.Lex(Tok);
3047
58
  }
3048
3049
54
  if (Tok.isNot(tok::eod)) {
3050
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3051
1
        << "clang fp";
3052
1
    return;
3053
1
  }
3054
3055
53
  Token FPTok;
3056
53
  FPTok.startToken();
3057
53
  FPTok.setKind(tok::annot_pragma_fp);
3058
53
  FPTok.setLocation(PragmaName.getLocation());
3059
53
  FPTok.setAnnotationEndLoc(PragmaName.getLocation());
3060
53
  FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
3061
53
  TokenList.push_back(FPTok);
3062
3063
53
  auto TokenArray = std::make_unique<Token[]>(TokenList.size());
3064
53
  std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
3065
3066
53
  PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
3067
53
                      /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3068
53
}
3069
3070
void PragmaSTDC_FENV_ROUNDHandler::HandlePragma(Preprocessor &PP,
3071
                                                PragmaIntroducer Introducer,
3072
39
                                                Token &Tok) {
3073
39
  Token PragmaName = Tok;
3074
39
  SmallVector<Token, 1> TokenList;
3075
39
  if (!PP.getTargetInfo().hasStrictFP() && 
!PP.getLangOpts().ExpStrictFP3
) {
3076
3
    PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
3077
3
        << PragmaName.getIdentifierInfo()->getName();
3078
3
    return;
3079
3
  }
3080
3081
36
  PP.Lex(Tok);
3082
36
  if (Tok.isNot(tok::identifier)) {
3083
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
3084
0
        << PragmaName.getIdentifierInfo()->getName();
3085
0
    return;
3086
0
  }
3087
36
  IdentifierInfo *II = Tok.getIdentifierInfo();
3088
3089
36
  auto RM =
3090
36
      llvm::StringSwitch<llvm::RoundingMode>(II->getName())
3091
36
          .Case("FE_TOWARDZERO", llvm::RoundingMode::TowardZero)
3092
36
          .Case("FE_TONEAREST", llvm::RoundingMode::NearestTiesToEven)
3093
36
          .Case("FE_UPWARD", llvm::RoundingMode::TowardPositive)
3094
36
          .Case("FE_DOWNWARD", llvm::RoundingMode::TowardNegative)
3095
36
          .Case("FE_TONEARESTFROMZERO", llvm::RoundingMode::NearestTiesToAway)
3096
36
          .Case("FE_DYNAMIC", llvm::RoundingMode::Dynamic)
3097
36
          .Default(llvm::RoundingMode::Invalid);
3098
36
  if (RM == llvm::RoundingMode::Invalid) {
3099
1
    PP.Diag(Tok.getLocation(), diag::warn_stdc_unknown_rounding_mode);
3100
1
    return;
3101
1
  }
3102
35
  PP.Lex(Tok);
3103
3104
35
  if (Tok.isNot(tok::eod)) {
3105
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3106
0
        << "STDC FENV_ROUND";
3107
0
    return;
3108
0
  }
3109
3110
  // Until the pragma is fully implemented, issue a warning.
3111
35
  PP.Diag(Tok.getLocation(), diag::warn_stdc_fenv_round_not_supported);
3112
3113
35
  MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
3114
35
                              1);
3115
35
  Toks[0].startToken();
3116
35
  Toks[0].setKind(tok::annot_pragma_fenv_round);
3117
35
  Toks[0].setLocation(Tok.getLocation());
3118
35
  Toks[0].setAnnotationEndLoc(Tok.getLocation());
3119
35
  Toks[0].setAnnotationValue(
3120
35
      reinterpret_cast<void *>(static_cast<uintptr_t>(RM)));
3121
35
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
3122
35
                      /*IsReinject=*/false);
3123
35
}
3124
3125
50
void Parser::HandlePragmaFP() {
3126
50
  assert(Tok.is(tok::annot_pragma_fp));
3127
50
  auto *AnnotValue =
3128
50
      reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
3129
3130
50
  if (AnnotValue->ReassociateValue)
3131
10
    Actions.ActOnPragmaFPReassociate(Tok.getLocation(),
3132
10
                                     *AnnotValue->ReassociateValue ==
3133
10
                                         LangOptions::FPModeKind::FPM_On);
3134
50
  if (AnnotValue->ContractValue)
3135
39
    Actions.ActOnPragmaFPContract(Tok.getLocation(),
3136
39
                                  *AnnotValue->ContractValue);
3137
50
  if (AnnotValue->ExceptionsValue)
3138
3
    Actions.ActOnPragmaFPExceptions(Tok.getLocation(),
3139
3
                                    *AnnotValue->ExceptionsValue);
3140
50
  ConsumeAnnotationToken();
3141
50
}
3142
3143
/// Parses loop or unroll pragma hint value and fills in Info.
3144
static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
3145
                               Token Option, bool ValueInParens,
3146
366
                               PragmaLoopHintInfo &Info) {
3147
366
  SmallVector<Token, 1> ValueList;
3148
348
  int OpenParens = ValueInParens ? 1 : 
018
;
3149
  // Read constant expression.
3150
823
  while (Tok.isNot(tok::eod)) {
3151
788
    if (Tok.is(tok::l_paren))
3152
8
      OpenParens++;
3153
780
    else if (Tok.is(tok::r_paren)) {
3154
338
      OpenParens--;
3155
338
      if (OpenParens == 0 && 
ValueInParens331
)
3156
331
        break;
3157
457
    }
3158
3159
457
    ValueList.push_back(Tok);
3160
457
    PP.Lex(Tok);
3161
457
  }
3162
3163
366
  if (ValueInParens) {
3164
    // Read ')'
3165
348
    if (Tok.isNot(tok::r_paren)) {
3166
17
      PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3167
17
      return true;
3168
17
    }
3169
331
    PP.Lex(Tok);
3170
331
  }
3171
3172
349
  Token EOFTok;
3173
349
  EOFTok.startToken();
3174
349
  EOFTok.setKind(tok::eof);
3175
349
  EOFTok.setLocation(Tok.getLocation());
3176
349
  ValueList.push_back(EOFTok); // Terminates expression for parsing.
3177
3178
349
  Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
3179
3180
349
  Info.PragmaName = PragmaName;
3181
349
  Info.Option = Option;
3182
349
  return false;
3183
366
}
3184
3185
/// Handle the \#pragma clang loop directive.
3186
///  #pragma clang 'loop' loop-hints
3187
///
3188
///  loop-hints:
3189
///    loop-hint loop-hints[opt]
3190
///
3191
///  loop-hint:
3192
///    'vectorize' '(' loop-hint-keyword ')'
3193
///    'interleave' '(' loop-hint-keyword ')'
3194
///    'unroll' '(' unroll-hint-keyword ')'
3195
///    'vectorize_predicate' '(' loop-hint-keyword ')'
3196
///    'vectorize_width' '(' loop-hint-value ')'
3197
///    'interleave_count' '(' loop-hint-value ')'
3198
///    'unroll_count' '(' loop-hint-value ')'
3199
///    'pipeline' '(' disable ')'
3200
///    'pipeline_initiation_interval' '(' loop-hint-value ')'
3201
///
3202
///  loop-hint-keyword:
3203
///    'enable'
3204
///    'disable'
3205
///    'assume_safety'
3206
///
3207
///  unroll-hint-keyword:
3208
///    'enable'
3209
///    'disable'
3210
///    'full'
3211
///
3212
///  loop-hint-value:
3213
///    constant-expression
3214
///
3215
/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
3216
/// try vectorizing the instructions of the loop it precedes. Specifying
3217
/// interleave(enable) or interleave_count(_value_) instructs llvm to try
3218
/// interleaving multiple iterations of the loop it precedes. The width of the
3219
/// vector instructions is specified by vectorize_width() and the number of
3220
/// interleaved loop iterations is specified by interleave_count(). Specifying a
3221
/// value of 1 effectively disables vectorization/interleaving, even if it is
3222
/// possible and profitable, and 0 is invalid. The loop vectorizer currently
3223
/// only works on inner loops.
3224
///
3225
/// The unroll and unroll_count directives control the concatenation
3226
/// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
3227
/// completely if the trip count is known at compile time and unroll partially
3228
/// if the trip count is not known.  Specifying unroll(full) is similar to
3229
/// unroll(enable) but will unroll the loop only if the trip count is known at
3230
/// compile time.  Specifying unroll(disable) disables unrolling for the
3231
/// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
3232
/// loop the number of times indicated by the value.
3233
void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
3234
                                         PragmaIntroducer Introducer,
3235
265
                                         Token &Tok) {
3236
  // Incoming token is "loop" from "#pragma clang loop".
3237
265
  Token PragmaName = Tok;
3238
265
  SmallVector<Token, 1> TokenList;
3239
3240
  // Lex the optimization option and verify it is an identifier.
3241
265
  PP.Lex(Tok);
3242
265
  if (Tok.isNot(tok::identifier)) {
3243
1
    PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
3244
1
        << /*MissingOption=*/true << "";
3245
1
    return;
3246
1
  }
3247
3248
567
  
while (264
Tok.is(tok::identifier)) {
3249
328
    Token Option = Tok;
3250
328
    IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
3251
3252
328
    bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
3253
328
                           .Case("vectorize", true)
3254
328
                           .Case("interleave", true)
3255
328
                           .Case("unroll", true)
3256
328
                           .Case("distribute", true)
3257
328
                           .Case("vectorize_predicate", true)
3258
328
                           .Case("vectorize_width", true)
3259
328
                           .Case("interleave_count", true)
3260
328
                           .Case("unroll_count", true)
3261
328
                           .Case("pipeline", true)
3262
328
                           .Case("pipeline_initiation_interval", true)
3263
328
                           .Default(false);
3264
328
    if (!OptionValid) {
3265
4
      PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
3266
4
          << /*MissingOption=*/false << OptionInfo;
3267
4
      return;
3268
4
    }
3269
324
    PP.Lex(Tok);
3270
3271
    // Read '('
3272
324
    if (Tok.isNot(tok::l_paren)) {
3273
7
      PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3274
7
      return;
3275
7
    }
3276
317
    PP.Lex(Tok);
3277
3278
317
    auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
3279
317
    if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
3280
317
                           *Info))
3281
14
      return;
3282
3283
    // Generate the loop hint token.
3284
303
    Token LoopHintTok;
3285
303
    LoopHintTok.startToken();
3286
303
    LoopHintTok.setKind(tok::annot_pragma_loop_hint);
3287
303
    LoopHintTok.setLocation(Introducer.Loc);
3288
303
    LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
3289
303
    LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
3290
303
    TokenList.push_back(LoopHintTok);
3291
303
  }
3292
3293
239
  if (Tok.isNot(tok::eod)) {
3294
4
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3295
4
        << "clang loop";
3296
4
    return;
3297
4
  }
3298
3299
235
  auto TokenArray = std::make_unique<Token[]>(TokenList.size());
3300
235
  std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
3301
3302
235
  PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
3303
235
                      /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3304
235
}
3305
3306
/// Handle the loop unroll optimization pragmas.
3307
///  #pragma unroll
3308
///  #pragma unroll unroll-hint-value
3309
///  #pragma unroll '(' unroll-hint-value ')'
3310
///  #pragma nounroll
3311
///  #pragma unroll_and_jam
3312
///  #pragma unroll_and_jam unroll-hint-value
3313
///  #pragma unroll_and_jam '(' unroll-hint-value ')'
3314
///  #pragma nounroll_and_jam
3315
///
3316
///  unroll-hint-value:
3317
///    constant-expression
3318
///
3319
/// Loop unrolling hints can be specified with '#pragma unroll' or
3320
/// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
3321
/// contained in parentheses. With no argument the directive instructs llvm to
3322
/// try to unroll the loop completely. A positive integer argument can be
3323
/// specified to indicate the number of times the loop should be unrolled.  To
3324
/// maximize compatibility with other compilers the unroll count argument can be
3325
/// specified with or without parentheses.  Specifying, '#pragma nounroll'
3326
/// disables unrolling of the loop.
3327
void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
3328
                                           PragmaIntroducer Introducer,
3329
85
                                           Token &Tok) {
3330
  // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
3331
  // "#pragma nounroll".
3332
85
  Token PragmaName = Tok;
3333
85
  PP.Lex(Tok);
3334
85
  auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
3335
85
  if (Tok.is(tok::eod)) {
3336
    // nounroll or unroll pragma without an argument.
3337
34
    Info->PragmaName = PragmaName;
3338
34
    Info->Option.startToken();
3339
51
  } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" ||
3340
50
             PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam") {
3341
2
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3342
2
        << PragmaName.getIdentifierInfo()->getName();
3343
2
    return;
3344
49
  } else {
3345
    // Unroll pragma with an argument: "#pragma unroll N" or
3346
    // "#pragma unroll(N)".
3347
    // Read '(' if it exists.
3348
49
    bool ValueInParens = Tok.is(tok::l_paren);
3349
49
    if (ValueInParens)
3350
31
      PP.Lex(Tok);
3351
3352
49
    Token Option;
3353
49
    Option.startToken();
3354
49
    if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
3355
3
      return;
3356
3357
    // In CUDA, the argument to '#pragma unroll' should not be contained in
3358
    // parentheses.
3359
46
    if (PP.getLangOpts().CUDA && 
ValueInParens2
)
3360
2
      PP.Diag(Info->Toks[0].getLocation(),
3361
2
              diag::warn_pragma_unroll_cuda_value_in_parens);
3362
3363
46
    if (Tok.isNot(tok::eod)) {
3364
0
      PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3365
0
          << "unroll";
3366
0
      return;
3367
0
    }
3368
80
  }
3369
3370
  // Generate the hint token.
3371
80
  auto TokenArray = std::make_unique<Token[]>(1);
3372
80
  TokenArray[0].startToken();
3373
80
  TokenArray[0].setKind(tok::annot_pragma_loop_hint);
3374
80
  TokenArray[0].setLocation(Introducer.Loc);
3375
80
  TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
3376
80
  TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
3377
80
  PP.EnterTokenStream(std::move(TokenArray), 1,
3378
80
                      /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3379
80
}
3380
3381
/// Handle the Microsoft \#pragma intrinsic extension.
3382
///
3383
/// The syntax is:
3384
/// \code
3385
///  #pragma intrinsic(memset)
3386
///  #pragma intrinsic(strlen, memcpy)
3387
/// \endcode
3388
///
3389
/// Pragma intrisic tells the compiler to use a builtin version of the
3390
/// function. Clang does it anyway, so the pragma doesn't really do anything.
3391
/// Anyway, we emit a warning if the function specified in \#pragma intrinsic
3392
/// isn't an intrinsic in clang and suggest to include intrin.h.
3393
void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
3394
                                            PragmaIntroducer Introducer,
3395
15
                                            Token &Tok) {
3396
15
  PP.Lex(Tok);
3397
3398
15
  if (Tok.isNot(tok::l_paren)) {
3399
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
3400
0
        << "intrinsic";
3401
0
    return;
3402
0
  }
3403
15
  PP.Lex(Tok);
3404
3405
15
  bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
3406
3407
17
  while (Tok.is(tok::identifier)) {
3408
14
    IdentifierInfo *II = Tok.getIdentifierInfo();
3409
14
    if (!II->getBuiltinID())
3410
8
      PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
3411
8
          << II << SuggestIntrinH;
3412
3413
14
    PP.Lex(Tok);
3414
14
    if (Tok.isNot(tok::comma))
3415
12
      break;
3416
2
    PP.Lex(Tok);
3417
2
  }
3418
3419
15
  if (Tok.isNot(tok::r_paren)) {
3420
2
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
3421
2
        << "intrinsic";
3422
2
    return;
3423
2
  }
3424
13
  PP.Lex(Tok);
3425
3426
13
  if (Tok.isNot(tok::eod))
3427
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3428
1
        << "intrinsic";
3429
13
}
3430
3431
// #pragma optimize("gsty", on|off)
3432
void PragmaMSOptimizeHandler::HandlePragma(Preprocessor &PP,
3433
                                           PragmaIntroducer Introducer,
3434
7
                                           Token &Tok) {
3435
7
  SourceLocation StartLoc = Tok.getLocation();
3436
7
  PP.Lex(Tok);
3437
3438
7
  if (Tok.isNot(tok::l_paren)) {
3439
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "optimize";
3440
1
    return;
3441
1
  }
3442
6
  PP.Lex(Tok);
3443
3444
6
  if (Tok.isNot(tok::string_literal)) {
3445
2
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_string) << "optimize";
3446
2
    return;
3447
2
  }
3448
  // We could syntax check the string but it's probably not worth the effort.
3449
4
  PP.Lex(Tok);
3450
3451
4
  if (Tok.isNot(tok::comma)) {
3452
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_comma) << "optimize";
3453
1
    return;
3454
1
  }
3455
3
  PP.Lex(Tok);
3456
3457
3
  if (Tok.is(tok::eod) || 
Tok.is(tok::r_paren)2
) {
3458
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_missing_argument)
3459
1
        << "optimize" << /*Expected=*/true << "'on' or 'off'";
3460
1
    return;
3461
1
  }
3462
2
  IdentifierInfo *II = Tok.getIdentifierInfo();
3463
2
  if (!II || (!II->isStr("on") && 
!II->isStr("off")1
)) {
3464
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
3465
1
        << PP.getSpelling(Tok) << "optimize" << /*Expected=*/true
3466
1
        << "'on' or 'off'";
3467
1
    return;
3468
1
  }
3469
1
  PP.Lex(Tok);
3470
3471
1
  if (Tok.isNot(tok::r_paren)) {
3472
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "optimize";
3473
0
    return;
3474
0
  }
3475
1
  PP.Lex(Tok);
3476
3477
1
  if (Tok.isNot(tok::eod)) {
3478
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3479
0
        << "optimize";
3480
0
    return;
3481
0
  }
3482
1
  PP.Diag(StartLoc, diag::warn_pragma_optimize);
3483
1
}
3484
3485
void PragmaForceCUDAHostDeviceHandler::HandlePragma(
3486
30
    Preprocessor &PP, PragmaIntroducer Introducer, Token &Tok) {
3487
30
  Token FirstTok = Tok;
3488
3489
30
  PP.Lex(Tok);
3490
30
  IdentifierInfo *Info = Tok.getIdentifierInfo();
3491
30
  if (!Info || 
(29
!Info->isStr("begin")29
&&
!Info->isStr("end")14
)) {
3492
2
    PP.Diag(FirstTok.getLocation(),
3493
2
            diag::warn_pragma_force_cuda_host_device_bad_arg);
3494
2
    return;
3495
2
  }
3496
3497
28
  if (Info->isStr("begin"))
3498
15
    Actions.PushForceCUDAHostDevice();
3499
13
  else if (!Actions.PopForceCUDAHostDevice())
3500
0
    PP.Diag(FirstTok.getLocation(),
3501
0
            diag::err_pragma_cannot_end_force_cuda_host_device);
3502
3503
28
  PP.Lex(Tok);
3504
28
  if (!Tok.is(tok::eod))
3505
1
    PP.Diag(FirstTok.getLocation(),
3506
1
            diag::warn_pragma_force_cuda_host_device_bad_arg);
3507
28
}
3508
3509
/// Handle the #pragma clang attribute directive.
3510
///
3511
/// The syntax is:
3512
/// \code
3513
///  #pragma clang attribute push (attribute, subject-set)
3514
///  #pragma clang attribute push
3515
///  #pragma clang attribute (attribute, subject-set)
3516
///  #pragma clang attribute pop
3517
/// \endcode
3518
///
3519
/// There are also 'namespace' variants of push and pop directives. The bare
3520
/// '#pragma clang attribute (attribute, subject-set)' version doesn't require a
3521
/// namespace, since it always applies attributes to the most recently pushed
3522
/// group, regardless of namespace.
3523
/// \code
3524
///  #pragma clang attribute namespace.push (attribute, subject-set)
3525
///  #pragma clang attribute namespace.push
3526
///  #pragma clang attribute namespace.pop
3527
/// \endcode
3528
///
3529
/// The subject-set clause defines the set of declarations which receive the
3530
/// attribute. Its exact syntax is described in the LanguageExtensions document
3531
/// in Clang's documentation.
3532
///
3533
/// This directive instructs the compiler to begin/finish applying the specified
3534
/// attribute to the set of attribute-specific declarations in the active range
3535
/// of the pragma.
3536
void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
3537
                                          PragmaIntroducer Introducer,
3538
3.11k
                                          Token &FirstToken) {
3539
3.11k
  Token Tok;
3540
3.11k
  PP.Lex(Tok);
3541
3.11k
  auto *Info = new (PP.getPreprocessorAllocator())
3542
3.11k
      PragmaAttributeInfo(AttributesForPragmaAttribute);
3543
3544
  // Parse the optional namespace followed by a period.
3545
3.11k
  if (Tok.is(tok::identifier)) {
3546
2.21k
    IdentifierInfo *II = Tok.getIdentifierInfo();
3547
2.21k
    if (!II->isStr("push") && 
!II->isStr("pop")1.05k
) {
3548
16
      Info->Namespace = II;
3549
16
      PP.Lex(Tok);
3550
3551
16
      if (!Tok.is(tok::period)) {
3552
2
        PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period)
3553
2
            << II;
3554
2
        return;
3555
2
      }
3556
14
      PP.Lex(Tok);
3557
14
    }
3558
2.21k
  }
3559
3560
3.11k
  if (!Tok.isOneOf(tok::identifier, tok::l_paren)) {
3561
2
    PP.Diag(Tok.getLocation(),
3562
2
            diag::err_pragma_attribute_expected_push_pop_paren);
3563
2
    return;
3564
2
  }
3565
3566
  // Determine what action this pragma clang attribute represents.
3567
3.10k
  if (Tok.is(tok::l_paren)) {
3568
892
    if (Info->Namespace) {
3569
1
      PP.Diag(Tok.getLocation(),
3570
1
              diag::err_pragma_attribute_namespace_on_attribute);
3571
1
      PP.Diag(Tok.getLocation(),
3572
1
              diag::note_pragma_attribute_namespace_on_attribute);
3573
1
      return;
3574
1
    }
3575
891
    Info->Action = PragmaAttributeInfo::Attribute;
3576
2.21k
  } else {
3577
2.21k
    const IdentifierInfo *II = Tok.getIdentifierInfo();
3578
2.21k
    if (II->isStr("push"))
3579
1.16k
      Info->Action = PragmaAttributeInfo::Push;
3580
1.04k
    else if (II->isStr("pop"))
3581
1.04k
      Info->Action = PragmaAttributeInfo::Pop;
3582
0
    else {
3583
0
      PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
3584
0
          << PP.getSpelling(Tok);
3585
0
      return;
3586
0
    }
3587
3588
2.21k
    PP.Lex(Tok);
3589
2.21k
  }
3590
3591
  // Parse the actual attribute.
3592
3.10k
  if ((Info->Action == PragmaAttributeInfo::Push && 
Tok.isNot(tok::eod)1.16k
) ||
3593
2.83k
      Info->Action == PragmaAttributeInfo::Attribute) {
3594
1.16k
    if (Tok.isNot(tok::l_paren)) {
3595
0
      PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3596
0
      return;
3597
0
    }
3598
1.16k
    PP.Lex(Tok);
3599
3600
    // Lex the attribute tokens.
3601
1.16k
    SmallVector<Token, 16> AttributeTokens;
3602
1.16k
    int OpenParens = 1;
3603
41.3k
    while (Tok.isNot(tok::eod)) {
3604
41.2k
      if (Tok.is(tok::l_paren))
3605
4.57k
        OpenParens++;
3606
36.7k
      else if (Tok.is(tok::r_paren)) {
3607
5.72k
        OpenParens--;
3608
5.72k
        if (OpenParens == 0)
3609
1.15k
          break;
3610
40.1k
      }
3611
3612
40.1k
      AttributeTokens.push_back(Tok);
3613
40.1k
      PP.Lex(Tok);
3614
40.1k
    }
3615
3616
1.16k
    if (AttributeTokens.empty()) {
3617
2
      PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);
3618
2
      return;
3619
2
    }
3620
1.16k
    if (Tok.isNot(tok::r_paren)) {
3621
10
      PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3622
10
      return;
3623
10
    }
3624
1.15k
    SourceLocation EndLoc = Tok.getLocation();
3625
1.15k
    PP.Lex(Tok);
3626
3627
    // Terminate the attribute for parsing.
3628
1.15k
    Token EOFTok;
3629
1.15k
    EOFTok.startToken();
3630
1.15k
    EOFTok.setKind(tok::eof);
3631
1.15k
    EOFTok.setLocation(EndLoc);
3632
1.15k
    AttributeTokens.push_back(EOFTok);
3633
3634
1.15k
    Info->Tokens =
3635
1.15k
        llvm::makeArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
3636
1.15k
  }
3637
3638
3.09k
  if (Tok.isNot(tok::eod))
3639
2
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3640
2
        << "clang attribute";
3641
3642
  // Generate the annotated pragma token.
3643
3.09k
  auto TokenArray = std::make_unique<Token[]>(1);
3644
3.09k
  TokenArray[0].startToken();
3645
3.09k
  TokenArray[0].setKind(tok::annot_pragma_attribute);
3646
3.09k
  TokenArray[0].setLocation(FirstToken.getLocation());
3647
3.09k
  TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation());
3648
3.09k
  TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
3649
3.09k
  PP.EnterTokenStream(std::move(TokenArray), 1,
3650
3.09k
                      /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3651
3.09k
}
3652
3653
// Handle '#pragma clang max_tokens 12345'.
3654
void PragmaMaxTokensHereHandler::HandlePragma(Preprocessor &PP,
3655
                                              PragmaIntroducer Introducer,
3656
12
                                              Token &Tok) {
3657
12
  PP.Lex(Tok);
3658
12
  if (Tok.is(tok::eod)) {
3659
3
    PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
3660
3
        << "clang max_tokens_here" << /*Expected=*/true << "integer";
3661
3
    return;
3662
3
  }
3663
3664
9
  SourceLocation Loc = Tok.getLocation();
3665
9
  uint64_t MaxTokens;
3666
9
  if (Tok.isNot(tok::numeric_constant) ||
3667
6
      !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
3668
3
    PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
3669
3
        << "clang max_tokens_here";
3670
3
    return;
3671
3
  }
3672
3673
6
  if (Tok.isNot(tok::eod)) {
3674
3
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3675
3
        << "clang max_tokens_here";
3676
3
    return;
3677
3
  }
3678
3679
3
  if (PP.getTokenCount() > MaxTokens) {
3680
3
    PP.Diag(Loc, diag::warn_max_tokens)
3681
3
        << PP.getTokenCount() << (unsigned)MaxTokens;
3682
3
  }
3683
3
}
3684
3685
// Handle '#pragma clang max_tokens_total 12345'.
3686
void PragmaMaxTokensTotalHandler::HandlePragma(Preprocessor &PP,
3687
                                               PragmaIntroducer Introducer,
3688
10
                                               Token &Tok) {
3689
10
  PP.Lex(Tok);
3690
10
  if (Tok.is(tok::eod)) {
3691
3
    PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
3692
3
        << "clang max_tokens_total" << /*Expected=*/true << "integer";
3693
3
    return;
3694
3
  }
3695
3696
7
  SourceLocation Loc = Tok.getLocation();
3697
7
  uint64_t MaxTokens;
3698
7
  if (Tok.isNot(tok::numeric_constant) ||
3699
4
      !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
3700
3
    PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
3701
3
        << "clang max_tokens_total";
3702
3
    return;
3703
3
  }
3704
3705
4
  if (Tok.isNot(tok::eod)) {
3706
3
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3707
3
        << "clang max_tokens_total";
3708
3
    return;
3709
3
  }
3710
3711
1
  PP.overrideMaxTokens(MaxTokens, Loc);
3712
1
}