Coverage Report

Created: 2020-03-31 06:27

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