1193326Sed//===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9193326Sed//
10193326Sed// This file implements the language specific #pragma handlers.
11193326Sed//
12193326Sed//===----------------------------------------------------------------------===//
13193326Sed
14193326Sed#include "ParsePragma.h"
15252723Sdim#include "clang/Lex/Preprocessor.h"
16193326Sed#include "clang/Parse/ParseDiagnostic.h"
17212904Sdim#include "clang/Parse/Parser.h"
18252723Sdim#include "clang/Sema/Scope.h"
19252723Sdim#include "llvm/ADT/StringSwitch.h"
20193326Sedusing namespace clang;
21193326Sed
22218893Sdim/// \brief Handle the annotation token produced for #pragma unused(...)
23218893Sdim///
24218893Sdim/// Each annot_pragma_unused is followed by the argument token so e.g.
25218893Sdim/// "#pragma unused(x,y)" becomes:
26218893Sdim/// annot_pragma_unused 'x' annot_pragma_unused 'y'
27218893Sdimvoid Parser::HandlePragmaUnused() {
28218893Sdim  assert(Tok.is(tok::annot_pragma_unused));
29218893Sdim  SourceLocation UnusedLoc = ConsumeToken();
30218893Sdim  Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
31218893Sdim  ConsumeToken(); // The argument token.
32218893Sdim}
33212904Sdim
34235633Sdimvoid Parser::HandlePragmaVisibility() {
35235633Sdim  assert(Tok.is(tok::annot_pragma_vis));
36235633Sdim  const IdentifierInfo *VisType =
37235633Sdim    static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
38235633Sdim  SourceLocation VisLoc = ConsumeToken();
39235633Sdim  Actions.ActOnPragmaVisibility(VisType, VisLoc);
40235633Sdim}
41235633Sdim
42235633Sdimstruct PragmaPackInfo {
43235633Sdim  Sema::PragmaPackKind Kind;
44235633Sdim  IdentifierInfo *Name;
45245431Sdim  Token Alignment;
46235633Sdim  SourceLocation LParenLoc;
47235633Sdim  SourceLocation RParenLoc;
48235633Sdim};
49235633Sdim
50235633Sdimvoid Parser::HandlePragmaPack() {
51235633Sdim  assert(Tok.is(tok::annot_pragma_pack));
52235633Sdim  PragmaPackInfo *Info =
53235633Sdim    static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
54235633Sdim  SourceLocation PragmaLoc = ConsumeToken();
55245431Sdim  ExprResult Alignment;
56245431Sdim  if (Info->Alignment.is(tok::numeric_constant)) {
57245431Sdim    Alignment = Actions.ActOnNumericConstant(Info->Alignment);
58245431Sdim    if (Alignment.isInvalid())
59245431Sdim      return;
60245431Sdim  }
61245431Sdim  Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
62235633Sdim                          Info->LParenLoc, Info->RParenLoc);
63235633Sdim}
64235633Sdim
65245431Sdimvoid Parser::HandlePragmaMSStruct() {
66245431Sdim  assert(Tok.is(tok::annot_pragma_msstruct));
67245431Sdim  Sema::PragmaMSStructKind Kind =
68245431Sdim    static_cast<Sema::PragmaMSStructKind>(
69245431Sdim    reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
70245431Sdim  Actions.ActOnPragmaMSStruct(Kind);
71245431Sdim  ConsumeToken(); // The annotation token.
72245431Sdim}
73245431Sdim
74245431Sdimvoid Parser::HandlePragmaAlign() {
75245431Sdim  assert(Tok.is(tok::annot_pragma_align));
76245431Sdim  Sema::PragmaOptionsAlignKind Kind =
77245431Sdim    static_cast<Sema::PragmaOptionsAlignKind>(
78245431Sdim    reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
79245431Sdim  SourceLocation PragmaLoc = ConsumeToken();
80245431Sdim  Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
81245431Sdim}
82245431Sdim
83245431Sdimvoid Parser::HandlePragmaWeak() {
84245431Sdim  assert(Tok.is(tok::annot_pragma_weak));
85245431Sdim  SourceLocation PragmaLoc = ConsumeToken();
86245431Sdim  Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
87245431Sdim                            Tok.getLocation());
88245431Sdim  ConsumeToken(); // The weak name.
89245431Sdim}
90245431Sdim
91245431Sdimvoid Parser::HandlePragmaWeakAlias() {
92245431Sdim  assert(Tok.is(tok::annot_pragma_weakalias));
93245431Sdim  SourceLocation PragmaLoc = ConsumeToken();
94245431Sdim  IdentifierInfo *WeakName = Tok.getIdentifierInfo();
95245431Sdim  SourceLocation WeakNameLoc = Tok.getLocation();
96245431Sdim  ConsumeToken();
97245431Sdim  IdentifierInfo *AliasName = Tok.getIdentifierInfo();
98245431Sdim  SourceLocation AliasNameLoc = Tok.getLocation();
99245431Sdim  ConsumeToken();
100245431Sdim  Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
101245431Sdim                               WeakNameLoc, AliasNameLoc);
102245431Sdim
103245431Sdim}
104245431Sdim
105245431Sdimvoid Parser::HandlePragmaRedefineExtname() {
106245431Sdim  assert(Tok.is(tok::annot_pragma_redefine_extname));
107245431Sdim  SourceLocation RedefLoc = ConsumeToken();
108245431Sdim  IdentifierInfo *RedefName = Tok.getIdentifierInfo();
109245431Sdim  SourceLocation RedefNameLoc = Tok.getLocation();
110245431Sdim  ConsumeToken();
111245431Sdim  IdentifierInfo *AliasName = Tok.getIdentifierInfo();
112245431Sdim  SourceLocation AliasNameLoc = Tok.getLocation();
113245431Sdim  ConsumeToken();
114245431Sdim  Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
115245431Sdim                                     RedefNameLoc, AliasNameLoc);
116245431Sdim}
117245431Sdim
118245431Sdimvoid Parser::HandlePragmaFPContract() {
119245431Sdim  assert(Tok.is(tok::annot_pragma_fp_contract));
120245431Sdim  tok::OnOffSwitch OOS =
121245431Sdim    static_cast<tok::OnOffSwitch>(
122245431Sdim    reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
123245431Sdim  Actions.ActOnPragmaFPContract(OOS);
124245431Sdim  ConsumeToken(); // The annotation token.
125245431Sdim}
126245431Sdim
127252723SdimStmtResult Parser::HandlePragmaCaptured()
128252723Sdim{
129252723Sdim  assert(Tok.is(tok::annot_pragma_captured));
130252723Sdim  ConsumeToken();
131252723Sdim
132252723Sdim  if (Tok.isNot(tok::l_brace)) {
133252723Sdim    PP.Diag(Tok, diag::err_expected_lbrace);
134252723Sdim    return StmtError();
135252723Sdim  }
136252723Sdim
137252723Sdim  SourceLocation Loc = Tok.getLocation();
138252723Sdim
139252723Sdim  ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
140252723Sdim  Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
141252723Sdim                                   /*NumParams=*/1);
142252723Sdim
143252723Sdim  StmtResult R = ParseCompoundStatement();
144252723Sdim  CapturedRegionScope.Exit();
145252723Sdim
146252723Sdim  if (R.isInvalid()) {
147252723Sdim    Actions.ActOnCapturedRegionError();
148252723Sdim    return StmtError();
149252723Sdim  }
150252723Sdim
151252723Sdim  return Actions.ActOnCapturedRegionEnd(R.get());
152252723Sdim}
153252723Sdim
154245431Sdimnamespace {
155245431Sdim  typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
156245431Sdim}
157245431Sdim
158245431Sdimvoid Parser::HandlePragmaOpenCLExtension() {
159245431Sdim  assert(Tok.is(tok::annot_pragma_opencl_extension));
160245431Sdim  OpenCLExtData data =
161245431Sdim      OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
162245431Sdim  unsigned state = data.getInt();
163245431Sdim  IdentifierInfo *ename = data.getPointer();
164245431Sdim  SourceLocation NameLoc = Tok.getLocation();
165245431Sdim  ConsumeToken(); // The annotation token.
166245431Sdim
167245431Sdim  OpenCLOptions &f = Actions.getOpenCLOptions();
168245431Sdim  // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
169245431Sdim  // overriding all previously issued extension directives, but only if the
170245431Sdim  // behavior is set to disable."
171245431Sdim  if (state == 0 && ename->isStr("all")) {
172245431Sdim#define OPENCLEXT(nm)   f.nm = 0;
173245431Sdim#include "clang/Basic/OpenCLExtensions.def"
174245431Sdim  }
175245431Sdim#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
176245431Sdim#include "clang/Basic/OpenCLExtensions.def"
177245431Sdim  else {
178245431Sdim    PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
179245431Sdim    return;
180245431Sdim  }
181245431Sdim}
182245431Sdim
183252723Sdim
184252723Sdim
185212904Sdim// #pragma GCC visibility comes in two variants:
186212904Sdim//   'push' '(' [visibility] ')'
187212904Sdim//   'pop'
188218893Sdimvoid PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
189218893Sdim                                              PragmaIntroducerKind Introducer,
190218893Sdim                                              Token &VisTok) {
191212904Sdim  SourceLocation VisLoc = VisTok.getLocation();
192212904Sdim
193212904Sdim  Token Tok;
194226890Sdim  PP.LexUnexpandedToken(Tok);
195212904Sdim
196212904Sdim  const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
197212904Sdim
198212904Sdim  const IdentifierInfo *VisType;
199212904Sdim  if (PushPop && PushPop->isStr("pop")) {
200212904Sdim    VisType = 0;
201212904Sdim  } else if (PushPop && PushPop->isStr("push")) {
202226890Sdim    PP.LexUnexpandedToken(Tok);
203212904Sdim    if (Tok.isNot(tok::l_paren)) {
204212904Sdim      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
205212904Sdim        << "visibility";
206212904Sdim      return;
207212904Sdim    }
208226890Sdim    PP.LexUnexpandedToken(Tok);
209212904Sdim    VisType = Tok.getIdentifierInfo();
210212904Sdim    if (!VisType) {
211212904Sdim      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
212212904Sdim        << "visibility";
213212904Sdim      return;
214212904Sdim    }
215226890Sdim    PP.LexUnexpandedToken(Tok);
216212904Sdim    if (Tok.isNot(tok::r_paren)) {
217212904Sdim      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
218212904Sdim        << "visibility";
219212904Sdim      return;
220212904Sdim    }
221212904Sdim  } else {
222212904Sdim    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
223212904Sdim      << "visibility";
224212904Sdim    return;
225212904Sdim  }
226226890Sdim  PP.LexUnexpandedToken(Tok);
227221345Sdim  if (Tok.isNot(tok::eod)) {
228212904Sdim    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
229212904Sdim      << "visibility";
230212904Sdim    return;
231212904Sdim  }
232212904Sdim
233235633Sdim  Token *Toks = new Token[1];
234235633Sdim  Toks[0].startToken();
235235633Sdim  Toks[0].setKind(tok::annot_pragma_vis);
236235633Sdim  Toks[0].setLocation(VisLoc);
237235633Sdim  Toks[0].setAnnotationValue(
238235633Sdim                          const_cast<void*>(static_cast<const void*>(VisType)));
239235633Sdim  PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
240235633Sdim                      /*OwnsTokens=*/true);
241212904Sdim}
242212904Sdim
243193326Sed// #pragma pack(...) comes in the following delicious flavors:
244193326Sed//   pack '(' [integer] ')'
245193326Sed//   pack '(' 'show' ')'
246193326Sed//   pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
247218893Sdimvoid PragmaPackHandler::HandlePragma(Preprocessor &PP,
248218893Sdim                                     PragmaIntroducerKind Introducer,
249218893Sdim                                     Token &PackTok) {
250193326Sed  SourceLocation PackLoc = PackTok.getLocation();
251193326Sed
252193326Sed  Token Tok;
253193326Sed  PP.Lex(Tok);
254193326Sed  if (Tok.isNot(tok::l_paren)) {
255193326Sed    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
256193326Sed    return;
257193326Sed  }
258193326Sed
259212904Sdim  Sema::PragmaPackKind Kind = Sema::PPK_Default;
260193326Sed  IdentifierInfo *Name = 0;
261245431Sdim  Token Alignment;
262245431Sdim  Alignment.startToken();
263193326Sed  SourceLocation LParenLoc = Tok.getLocation();
264198092Srdivacky  PP.Lex(Tok);
265193326Sed  if (Tok.is(tok::numeric_constant)) {
266245431Sdim    Alignment = Tok;
267193326Sed
268193326Sed    PP.Lex(Tok);
269235633Sdim
270235633Sdim    // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
271235633Sdim    // the push/pop stack.
272235633Sdim    // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
273235633Sdim    if (PP.getLangOpts().ApplePragmaPack)
274235633Sdim      Kind = Sema::PPK_Push;
275193326Sed  } else if (Tok.is(tok::identifier)) {
276193326Sed    const IdentifierInfo *II = Tok.getIdentifierInfo();
277193326Sed    if (II->isStr("show")) {
278212904Sdim      Kind = Sema::PPK_Show;
279193326Sed      PP.Lex(Tok);
280193326Sed    } else {
281193326Sed      if (II->isStr("push")) {
282212904Sdim        Kind = Sema::PPK_Push;
283193326Sed      } else if (II->isStr("pop")) {
284212904Sdim        Kind = Sema::PPK_Pop;
285193326Sed      } else {
286193326Sed        PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
287193326Sed        return;
288198092Srdivacky      }
289193326Sed      PP.Lex(Tok);
290198092Srdivacky
291193326Sed      if (Tok.is(tok::comma)) {
292193326Sed        PP.Lex(Tok);
293198092Srdivacky
294193326Sed        if (Tok.is(tok::numeric_constant)) {
295245431Sdim          Alignment = Tok;
296193326Sed
297193326Sed          PP.Lex(Tok);
298193326Sed        } else if (Tok.is(tok::identifier)) {
299193326Sed          Name = Tok.getIdentifierInfo();
300193326Sed          PP.Lex(Tok);
301198092Srdivacky
302193326Sed          if (Tok.is(tok::comma)) {
303193326Sed            PP.Lex(Tok);
304198092Srdivacky
305193326Sed            if (Tok.isNot(tok::numeric_constant)) {
306193326Sed              PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
307193326Sed              return;
308193326Sed            }
309198092Srdivacky
310245431Sdim            Alignment = Tok;
311193326Sed
312193326Sed            PP.Lex(Tok);
313193326Sed          }
314193326Sed        } else {
315193326Sed          PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
316193326Sed          return;
317193326Sed        }
318193326Sed      }
319193326Sed    }
320235633Sdim  } else if (PP.getLangOpts().ApplePragmaPack) {
321235633Sdim    // In MSVC/gcc, #pragma pack() resets the alignment without affecting
322235633Sdim    // the push/pop stack.
323235633Sdim    // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
324235633Sdim    Kind = Sema::PPK_Pop;
325193326Sed  }
326193326Sed
327193326Sed  if (Tok.isNot(tok::r_paren)) {
328193326Sed    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
329193326Sed    return;
330193326Sed  }
331193326Sed
332208600Srdivacky  SourceLocation RParenLoc = Tok.getLocation();
333193576Sed  PP.Lex(Tok);
334221345Sdim  if (Tok.isNot(tok::eod)) {
335193576Sed    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
336193576Sed    return;
337193576Sed  }
338193576Sed
339235633Sdim  PragmaPackInfo *Info =
340235633Sdim    (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
341235633Sdim      sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
342235633Sdim  new (Info) PragmaPackInfo();
343235633Sdim  Info->Kind = Kind;
344235633Sdim  Info->Name = Name;
345245431Sdim  Info->Alignment = Alignment;
346235633Sdim  Info->LParenLoc = LParenLoc;
347235633Sdim  Info->RParenLoc = RParenLoc;
348235633Sdim
349235633Sdim  Token *Toks =
350235633Sdim    (Token*) PP.getPreprocessorAllocator().Allocate(
351235633Sdim      sizeof(Token) * 1, llvm::alignOf<Token>());
352235633Sdim  new (Toks) Token();
353235633Sdim  Toks[0].startToken();
354235633Sdim  Toks[0].setKind(tok::annot_pragma_pack);
355235633Sdim  Toks[0].setLocation(PackLoc);
356235633Sdim  Toks[0].setAnnotationValue(static_cast<void*>(Info));
357235633Sdim  PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
358235633Sdim                      /*OwnsTokens=*/false);
359193326Sed}
360193326Sed
361221345Sdim// #pragma ms_struct on
362221345Sdim// #pragma ms_struct off
363221345Sdimvoid PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
364221345Sdim                                         PragmaIntroducerKind Introducer,
365221345Sdim                                         Token &MSStructTok) {
366221345Sdim  Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
367221345Sdim
368221345Sdim  Token Tok;
369221345Sdim  PP.Lex(Tok);
370221345Sdim  if (Tok.isNot(tok::identifier)) {
371221345Sdim    PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
372221345Sdim    return;
373221345Sdim  }
374221345Sdim  const IdentifierInfo *II = Tok.getIdentifierInfo();
375221345Sdim  if (II->isStr("on")) {
376221345Sdim    Kind = Sema::PMSST_ON;
377221345Sdim    PP.Lex(Tok);
378221345Sdim  }
379221345Sdim  else if (II->isStr("off") || II->isStr("reset"))
380221345Sdim    PP.Lex(Tok);
381221345Sdim  else {
382221345Sdim    PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
383221345Sdim    return;
384221345Sdim  }
385221345Sdim
386221345Sdim  if (Tok.isNot(tok::eod)) {
387235633Sdim    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
388235633Sdim      << "ms_struct";
389221345Sdim    return;
390221345Sdim  }
391245431Sdim
392245431Sdim  Token *Toks =
393245431Sdim    (Token*) PP.getPreprocessorAllocator().Allocate(
394245431Sdim      sizeof(Token) * 1, llvm::alignOf<Token>());
395245431Sdim  new (Toks) Token();
396245431Sdim  Toks[0].startToken();
397245431Sdim  Toks[0].setKind(tok::annot_pragma_msstruct);
398245431Sdim  Toks[0].setLocation(MSStructTok.getLocation());
399245431Sdim  Toks[0].setAnnotationValue(reinterpret_cast<void*>(
400245431Sdim                             static_cast<uintptr_t>(Kind)));
401245431Sdim  PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
402245431Sdim                      /*OwnsTokens=*/false);
403221345Sdim}
404221345Sdim
405212904Sdim// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
406212904Sdim// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
407245431Sdimstatic void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
408212904Sdim                             bool IsOptions) {
409212904Sdim  Token Tok;
410208600Srdivacky
411212904Sdim  if (IsOptions) {
412212904Sdim    PP.Lex(Tok);
413212904Sdim    if (Tok.isNot(tok::identifier) ||
414212904Sdim        !Tok.getIdentifierInfo()->isStr("align")) {
415212904Sdim      PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
416212904Sdim      return;
417212904Sdim    }
418208600Srdivacky  }
419210299Sed
420208600Srdivacky  PP.Lex(Tok);
421208600Srdivacky  if (Tok.isNot(tok::equal)) {
422212904Sdim    PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
423212904Sdim      << IsOptions;
424208600Srdivacky    return;
425208600Srdivacky  }
426208600Srdivacky
427208600Srdivacky  PP.Lex(Tok);
428208600Srdivacky  if (Tok.isNot(tok::identifier)) {
429208600Srdivacky    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
430212904Sdim      << (IsOptions ? "options" : "align");
431208600Srdivacky    return;
432208600Srdivacky  }
433208600Srdivacky
434212904Sdim  Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
435208600Srdivacky  const IdentifierInfo *II = Tok.getIdentifierInfo();
436210299Sed  if (II->isStr("native"))
437212904Sdim    Kind = Sema::POAK_Native;
438210299Sed  else if (II->isStr("natural"))
439212904Sdim    Kind = Sema::POAK_Natural;
440210299Sed  else if (II->isStr("packed"))
441212904Sdim    Kind = Sema::POAK_Packed;
442208600Srdivacky  else if (II->isStr("power"))
443212904Sdim    Kind = Sema::POAK_Power;
444208600Srdivacky  else if (II->isStr("mac68k"))
445212904Sdim    Kind = Sema::POAK_Mac68k;
446208600Srdivacky  else if (II->isStr("reset"))
447212904Sdim    Kind = Sema::POAK_Reset;
448208600Srdivacky  else {
449212904Sdim    PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
450212904Sdim      << IsOptions;
451208600Srdivacky    return;
452208600Srdivacky  }
453208600Srdivacky
454208600Srdivacky  PP.Lex(Tok);
455221345Sdim  if (Tok.isNot(tok::eod)) {
456208600Srdivacky    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
457212904Sdim      << (IsOptions ? "options" : "align");
458208600Srdivacky    return;
459208600Srdivacky  }
460208600Srdivacky
461245431Sdim  Token *Toks =
462245431Sdim    (Token*) PP.getPreprocessorAllocator().Allocate(
463245431Sdim      sizeof(Token) * 1, llvm::alignOf<Token>());
464245431Sdim  new (Toks) Token();
465245431Sdim  Toks[0].startToken();
466245431Sdim  Toks[0].setKind(tok::annot_pragma_align);
467245431Sdim  Toks[0].setLocation(FirstTok.getLocation());
468245431Sdim  Toks[0].setAnnotationValue(reinterpret_cast<void*>(
469245431Sdim                             static_cast<uintptr_t>(Kind)));
470245431Sdim  PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
471245431Sdim                      /*OwnsTokens=*/false);
472208600Srdivacky}
473208600Srdivacky
474218893Sdimvoid PragmaAlignHandler::HandlePragma(Preprocessor &PP,
475218893Sdim                                      PragmaIntroducerKind Introducer,
476218893Sdim                                      Token &AlignTok) {
477245431Sdim  ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
478212904Sdim}
479212904Sdim
480218893Sdimvoid PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
481218893Sdim                                        PragmaIntroducerKind Introducer,
482218893Sdim                                        Token &OptionsTok) {
483245431Sdim  ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
484212904Sdim}
485212904Sdim
486193326Sed// #pragma unused(identifier)
487218893Sdimvoid PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
488218893Sdim                                       PragmaIntroducerKind Introducer,
489218893Sdim                                       Token &UnusedTok) {
490193326Sed  // FIXME: Should we be expanding macros here? My guess is no.
491193326Sed  SourceLocation UnusedLoc = UnusedTok.getLocation();
492198092Srdivacky
493193326Sed  // Lex the left '('.
494193326Sed  Token Tok;
495193326Sed  PP.Lex(Tok);
496193326Sed  if (Tok.isNot(tok::l_paren)) {
497193326Sed    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
498193326Sed    return;
499193326Sed  }
500198092Srdivacky
501193326Sed  // Lex the declaration reference(s).
502226890Sdim  SmallVector<Token, 5> Identifiers;
503193326Sed  SourceLocation RParenLoc;
504193326Sed  bool LexID = true;
505198092Srdivacky
506193326Sed  while (true) {
507193326Sed    PP.Lex(Tok);
508198092Srdivacky
509193326Sed    if (LexID) {
510198092Srdivacky      if (Tok.is(tok::identifier)) {
511198092Srdivacky        Identifiers.push_back(Tok);
512193326Sed        LexID = false;
513193326Sed        continue;
514193326Sed      }
515193326Sed
516198092Srdivacky      // Illegal token!
517193326Sed      PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
518193326Sed      return;
519193326Sed    }
520198092Srdivacky
521193326Sed    // We are execting a ')' or a ','.
522193326Sed    if (Tok.is(tok::comma)) {
523193326Sed      LexID = true;
524193326Sed      continue;
525193326Sed    }
526198092Srdivacky
527193326Sed    if (Tok.is(tok::r_paren)) {
528193326Sed      RParenLoc = Tok.getLocation();
529193326Sed      break;
530193326Sed    }
531198092Srdivacky
532198092Srdivacky    // Illegal token!
533193326Sed    PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
534193326Sed    return;
535193326Sed  }
536193576Sed
537193576Sed  PP.Lex(Tok);
538221345Sdim  if (Tok.isNot(tok::eod)) {
539193576Sed    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
540193576Sed        "unused";
541193576Sed    return;
542193576Sed  }
543193576Sed
544193326Sed  // Verify that we have a location for the right parenthesis.
545193326Sed  assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
546198092Srdivacky  assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
547193326Sed
548218893Sdim  // For each identifier token, insert into the token stream a
549218893Sdim  // annot_pragma_unused token followed by the identifier token.
550218893Sdim  // This allows us to cache a "#pragma unused" that occurs inside an inline
551218893Sdim  // C++ member function.
552218893Sdim
553235633Sdim  Token *Toks =
554235633Sdim    (Token*) PP.getPreprocessorAllocator().Allocate(
555235633Sdim      sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
556218893Sdim  for (unsigned i=0; i != Identifiers.size(); i++) {
557218893Sdim    Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
558218893Sdim    pragmaUnusedTok.startToken();
559218893Sdim    pragmaUnusedTok.setKind(tok::annot_pragma_unused);
560218893Sdim    pragmaUnusedTok.setLocation(UnusedLoc);
561218893Sdim    idTok = Identifiers[i];
562218893Sdim  }
563235633Sdim  PP.EnterTokenStream(Toks, 2*Identifiers.size(),
564235633Sdim                      /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
565193326Sed}
566193576Sed
567193576Sed// #pragma weak identifier
568193576Sed// #pragma weak identifier '=' identifier
569218893Sdimvoid PragmaWeakHandler::HandlePragma(Preprocessor &PP,
570218893Sdim                                     PragmaIntroducerKind Introducer,
571218893Sdim                                     Token &WeakTok) {
572193576Sed  SourceLocation WeakLoc = WeakTok.getLocation();
573193576Sed
574193576Sed  Token Tok;
575193576Sed  PP.Lex(Tok);
576193576Sed  if (Tok.isNot(tok::identifier)) {
577193576Sed    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
578193576Sed    return;
579193576Sed  }
580193576Sed
581245431Sdim  Token WeakName = Tok;
582245431Sdim  bool HasAlias = false;
583245431Sdim  Token AliasName;
584193576Sed
585193576Sed  PP.Lex(Tok);
586193576Sed  if (Tok.is(tok::equal)) {
587245431Sdim    HasAlias = true;
588193576Sed    PP.Lex(Tok);
589193576Sed    if (Tok.isNot(tok::identifier)) {
590198092Srdivacky      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
591193576Sed          << "weak";
592193576Sed      return;
593193576Sed    }
594245431Sdim    AliasName = Tok;
595193576Sed    PP.Lex(Tok);
596193576Sed  }
597193576Sed
598221345Sdim  if (Tok.isNot(tok::eod)) {
599193576Sed    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
600193576Sed    return;
601193576Sed  }
602193576Sed
603245431Sdim  if (HasAlias) {
604245431Sdim    Token *Toks =
605245431Sdim      (Token*) PP.getPreprocessorAllocator().Allocate(
606245431Sdim        sizeof(Token) * 3, llvm::alignOf<Token>());
607245431Sdim    Token &pragmaUnusedTok = Toks[0];
608245431Sdim    pragmaUnusedTok.startToken();
609245431Sdim    pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
610245431Sdim    pragmaUnusedTok.setLocation(WeakLoc);
611245431Sdim    Toks[1] = WeakName;
612245431Sdim    Toks[2] = AliasName;
613245431Sdim    PP.EnterTokenStream(Toks, 3,
614245431Sdim                        /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
615193576Sed  } else {
616245431Sdim    Token *Toks =
617245431Sdim      (Token*) PP.getPreprocessorAllocator().Allocate(
618245431Sdim        sizeof(Token) * 2, llvm::alignOf<Token>());
619245431Sdim    Token &pragmaUnusedTok = Toks[0];
620245431Sdim    pragmaUnusedTok.startToken();
621245431Sdim    pragmaUnusedTok.setKind(tok::annot_pragma_weak);
622245431Sdim    pragmaUnusedTok.setLocation(WeakLoc);
623245431Sdim    Toks[1] = WeakName;
624245431Sdim    PP.EnterTokenStream(Toks, 2,
625245431Sdim                        /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
626193576Sed  }
627193576Sed}
628218893Sdim
629235633Sdim// #pragma redefine_extname identifier identifier
630235633Sdimvoid PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
631235633Sdim                                               PragmaIntroducerKind Introducer,
632235633Sdim                                                Token &RedefToken) {
633235633Sdim  SourceLocation RedefLoc = RedefToken.getLocation();
634235633Sdim
635235633Sdim  Token Tok;
636235633Sdim  PP.Lex(Tok);
637235633Sdim  if (Tok.isNot(tok::identifier)) {
638235633Sdim    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
639235633Sdim      "redefine_extname";
640235633Sdim    return;
641235633Sdim  }
642235633Sdim
643245431Sdim  Token RedefName = Tok;
644245431Sdim  PP.Lex(Tok);
645235633Sdim
646235633Sdim  if (Tok.isNot(tok::identifier)) {
647235633Sdim    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
648235633Sdim        << "redefine_extname";
649235633Sdim    return;
650235633Sdim  }
651245431Sdim
652245431Sdim  Token AliasName = Tok;
653235633Sdim  PP.Lex(Tok);
654235633Sdim
655235633Sdim  if (Tok.isNot(tok::eod)) {
656235633Sdim    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
657235633Sdim      "redefine_extname";
658235633Sdim    return;
659235633Sdim  }
660235633Sdim
661245431Sdim  Token *Toks =
662245431Sdim    (Token*) PP.getPreprocessorAllocator().Allocate(
663245431Sdim      sizeof(Token) * 3, llvm::alignOf<Token>());
664245431Sdim  Token &pragmaRedefTok = Toks[0];
665245431Sdim  pragmaRedefTok.startToken();
666245431Sdim  pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
667245431Sdim  pragmaRedefTok.setLocation(RedefLoc);
668245431Sdim  Toks[1] = RedefName;
669245431Sdim  Toks[2] = AliasName;
670245431Sdim  PP.EnterTokenStream(Toks, 3,
671245431Sdim                      /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
672235633Sdim}
673235633Sdim
674235633Sdim
675218893Sdimvoid
676218893SdimPragmaFPContractHandler::HandlePragma(Preprocessor &PP,
677218893Sdim                                      PragmaIntroducerKind Introducer,
678218893Sdim                                      Token &Tok) {
679218893Sdim  tok::OnOffSwitch OOS;
680218893Sdim  if (PP.LexOnOffSwitch(OOS))
681218893Sdim    return;
682218893Sdim
683245431Sdim  Token *Toks =
684245431Sdim    (Token*) PP.getPreprocessorAllocator().Allocate(
685245431Sdim      sizeof(Token) * 1, llvm::alignOf<Token>());
686245431Sdim  new (Toks) Token();
687245431Sdim  Toks[0].startToken();
688245431Sdim  Toks[0].setKind(tok::annot_pragma_fp_contract);
689245431Sdim  Toks[0].setLocation(Tok.getLocation());
690245431Sdim  Toks[0].setAnnotationValue(reinterpret_cast<void*>(
691245431Sdim                             static_cast<uintptr_t>(OOS)));
692245431Sdim  PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
693245431Sdim                      /*OwnsTokens=*/false);
694218893Sdim}
695218893Sdim
696218893Sdimvoid
697218893SdimPragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
698218893Sdim                                           PragmaIntroducerKind Introducer,
699218893Sdim                                           Token &Tok) {
700221345Sdim  PP.LexUnexpandedToken(Tok);
701218893Sdim  if (Tok.isNot(tok::identifier)) {
702218893Sdim    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
703218893Sdim      "OPENCL";
704218893Sdim    return;
705218893Sdim  }
706218893Sdim  IdentifierInfo *ename = Tok.getIdentifierInfo();
707218893Sdim  SourceLocation NameLoc = Tok.getLocation();
708218893Sdim
709218893Sdim  PP.Lex(Tok);
710218893Sdim  if (Tok.isNot(tok::colon)) {
711218893Sdim    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
712218893Sdim    return;
713218893Sdim  }
714218893Sdim
715218893Sdim  PP.Lex(Tok);
716218893Sdim  if (Tok.isNot(tok::identifier)) {
717218893Sdim    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
718218893Sdim    return;
719218893Sdim  }
720218893Sdim  IdentifierInfo *op = Tok.getIdentifierInfo();
721218893Sdim
722218893Sdim  unsigned state;
723218893Sdim  if (op->isStr("enable")) {
724218893Sdim    state = 1;
725218893Sdim  } else if (op->isStr("disable")) {
726218893Sdim    state = 0;
727218893Sdim  } else {
728218893Sdim    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
729218893Sdim    return;
730218893Sdim  }
731263509Sdim  SourceLocation StateLoc = Tok.getLocation();
732218893Sdim
733245431Sdim  PP.Lex(Tok);
734245431Sdim  if (Tok.isNot(tok::eod)) {
735245431Sdim    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
736245431Sdim      "OPENCL EXTENSION";
737218893Sdim    return;
738218893Sdim  }
739245431Sdim
740245431Sdim  OpenCLExtData data(ename, state);
741245431Sdim  Token *Toks =
742245431Sdim    (Token*) PP.getPreprocessorAllocator().Allocate(
743245431Sdim      sizeof(Token) * 1, llvm::alignOf<Token>());
744245431Sdim  new (Toks) Token();
745245431Sdim  Toks[0].startToken();
746245431Sdim  Toks[0].setKind(tok::annot_pragma_opencl_extension);
747245431Sdim  Toks[0].setLocation(NameLoc);
748245431Sdim  Toks[0].setAnnotationValue(data.getOpaqueValue());
749245431Sdim  PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
750245431Sdim                      /*OwnsTokens=*/false);
751263509Sdim
752263509Sdim  if (PP.getPPCallbacks())
753263509Sdim    PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename,
754263509Sdim                                               StateLoc, state);
755218893Sdim}
756218893Sdim
757252723Sdim/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
758252723Sdim///
759252723Sdimvoid
760252723SdimPragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
761252723Sdim                                    PragmaIntroducerKind Introducer,
762252723Sdim                                    Token &FirstTok) {
763252723Sdim  if (PP.getDiagnostics().getDiagnosticLevel(diag::warn_pragma_omp_ignored,
764252723Sdim                                             FirstTok.getLocation()) !=
765252723Sdim      DiagnosticsEngine::Ignored) {
766252723Sdim    PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
767252723Sdim    PP.getDiagnostics().setDiagnosticMapping(diag::warn_pragma_omp_ignored,
768252723Sdim                                             diag::MAP_IGNORE,
769252723Sdim                                             SourceLocation());
770252723Sdim  }
771252723Sdim  PP.DiscardUntilEndOfDirective();
772252723Sdim}
773252723Sdim
774252723Sdim/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
775252723Sdim///
776252723Sdimvoid
777252723SdimPragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
778252723Sdim                                  PragmaIntroducerKind Introducer,
779252723Sdim                                  Token &FirstTok) {
780252723Sdim  SmallVector<Token, 16> Pragma;
781252723Sdim  Token Tok;
782252723Sdim  Tok.startToken();
783252723Sdim  Tok.setKind(tok::annot_pragma_openmp);
784252723Sdim  Tok.setLocation(FirstTok.getLocation());
785252723Sdim
786252723Sdim  while (Tok.isNot(tok::eod)) {
787252723Sdim    Pragma.push_back(Tok);
788252723Sdim    PP.Lex(Tok);
789252723Sdim  }
790252723Sdim  SourceLocation EodLoc = Tok.getLocation();
791252723Sdim  Tok.startToken();
792252723Sdim  Tok.setKind(tok::annot_pragma_openmp_end);
793252723Sdim  Tok.setLocation(EodLoc);
794252723Sdim  Pragma.push_back(Tok);
795252723Sdim
796252723Sdim  Token *Toks = new Token[Pragma.size()];
797252723Sdim  std::copy(Pragma.begin(), Pragma.end(), Toks);
798252723Sdim  PP.EnterTokenStream(Toks, Pragma.size(),
799252723Sdim                      /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
800252723Sdim}
801252723Sdim
802263509Sdim/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
803263509Sdim///
804263509Sdim/// The syntax is:
805263509Sdim/// \code
806263509Sdim///   #pragma detect_mismatch("name", "value")
807263509Sdim/// \endcode
808263509Sdim/// Where 'name' and 'value' are quoted strings.  The values are embedded in
809263509Sdim/// the object file and passed along to the linker.  If the linker detects a
810263509Sdim/// mismatch in the object file's values for the given name, a LNK2038 error
811263509Sdim/// is emitted.  See MSDN for more details.
812263509Sdimvoid PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
813263509Sdim                                               PragmaIntroducerKind Introducer,
814263509Sdim                                               Token &Tok) {
815263509Sdim  SourceLocation CommentLoc = Tok.getLocation();
816263509Sdim  PP.Lex(Tok);
817263509Sdim  if (Tok.isNot(tok::l_paren)) {
818263509Sdim    PP.Diag(CommentLoc, diag::err_expected_lparen);
819263509Sdim    return;
820263509Sdim  }
821263509Sdim
822263509Sdim  // Read the name to embed, which must be a string literal.
823263509Sdim  std::string NameString;
824263509Sdim  if (!PP.LexStringLiteral(Tok, NameString,
825263509Sdim                           "pragma detect_mismatch",
826263509Sdim                           /*MacroExpansion=*/true))
827263509Sdim    return;
828263509Sdim
829263509Sdim  // Read the comma followed by a second string literal.
830263509Sdim  std::string ValueString;
831263509Sdim  if (Tok.isNot(tok::comma)) {
832263509Sdim    PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
833263509Sdim    return;
834263509Sdim  }
835263509Sdim
836263509Sdim  if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
837263509Sdim                           /*MacroExpansion=*/true))
838263509Sdim    return;
839263509Sdim
840263509Sdim  if (Tok.isNot(tok::r_paren)) {
841263509Sdim    PP.Diag(Tok.getLocation(), diag::err_expected_rparen);
842263509Sdim    return;
843263509Sdim  }
844263509Sdim  PP.Lex(Tok);  // Eat the r_paren.
845263509Sdim
846263509Sdim  if (Tok.isNot(tok::eod)) {
847263509Sdim    PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
848263509Sdim    return;
849263509Sdim  }
850263509Sdim
851263509Sdim  // If the pragma is lexically sound, notify any interested PPCallbacks.
852263509Sdim  if (PP.getPPCallbacks())
853263509Sdim    PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString,
854263509Sdim                                              ValueString);
855263509Sdim
856263509Sdim  Actions.ActOnPragmaDetectMismatch(NameString, ValueString);
857263509Sdim}
858263509Sdim
859252723Sdim/// \brief Handle the microsoft \#pragma comment extension.
860252723Sdim///
861252723Sdim/// The syntax is:
862252723Sdim/// \code
863252723Sdim///   #pragma comment(linker, "foo")
864252723Sdim/// \endcode
865252723Sdim/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
866252723Sdim/// "foo" is a string, which is fully macro expanded, and permits string
867252723Sdim/// concatenation, embedded escape characters etc.  See MSDN for more details.
868252723Sdimvoid PragmaCommentHandler::HandlePragma(Preprocessor &PP,
869252723Sdim                                        PragmaIntroducerKind Introducer,
870252723Sdim                                        Token &Tok) {
871252723Sdim  SourceLocation CommentLoc = Tok.getLocation();
872252723Sdim  PP.Lex(Tok);
873252723Sdim  if (Tok.isNot(tok::l_paren)) {
874252723Sdim    PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
875252723Sdim    return;
876252723Sdim  }
877252723Sdim
878252723Sdim  // Read the identifier.
879252723Sdim  PP.Lex(Tok);
880252723Sdim  if (Tok.isNot(tok::identifier)) {
881252723Sdim    PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
882252723Sdim    return;
883252723Sdim  }
884252723Sdim
885252723Sdim  // Verify that this is one of the 5 whitelisted options.
886263509Sdim  IdentifierInfo *II = Tok.getIdentifierInfo();
887263509Sdim  Sema::PragmaMSCommentKind Kind =
888263509Sdim    llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName())
889263509Sdim    .Case("linker",   Sema::PCK_Linker)
890263509Sdim    .Case("lib",      Sema::PCK_Lib)
891263509Sdim    .Case("compiler", Sema::PCK_Compiler)
892263509Sdim    .Case("exestr",   Sema::PCK_ExeStr)
893263509Sdim    .Case("user",     Sema::PCK_User)
894263509Sdim    .Default(Sema::PCK_Unknown);
895263509Sdim  if (Kind == Sema::PCK_Unknown) {
896252723Sdim    PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
897252723Sdim    return;
898252723Sdim  }
899252723Sdim
900252723Sdim  // Read the optional string if present.
901252723Sdim  PP.Lex(Tok);
902252723Sdim  std::string ArgumentString;
903252723Sdim  if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
904252723Sdim                                                 "pragma comment",
905252723Sdim                                                 /*MacroExpansion=*/true))
906252723Sdim    return;
907252723Sdim
908263509Sdim  // FIXME: warn that 'exestr' is deprecated.
909252723Sdim  // FIXME: If the kind is "compiler" warn if the string is present (it is
910252723Sdim  // ignored).
911263509Sdim  // The MSDN docs say that "lib" and "linker" require a string and have a short
912263509Sdim  // whitelist of linker options they support, but in practice MSVC doesn't
913263509Sdim  // issue a diagnostic.  Therefore neither does clang.
914252723Sdim
915252723Sdim  if (Tok.isNot(tok::r_paren)) {
916252723Sdim    PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
917252723Sdim    return;
918252723Sdim  }
919252723Sdim  PP.Lex(Tok);  // eat the r_paren.
920252723Sdim
921252723Sdim  if (Tok.isNot(tok::eod)) {
922252723Sdim    PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
923252723Sdim    return;
924252723Sdim  }
925252723Sdim
926252723Sdim  // If the pragma is lexically sound, notify any interested PPCallbacks.
927252723Sdim  if (PP.getPPCallbacks())
928252723Sdim    PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
929263509Sdim
930263509Sdim  Actions.ActOnPragmaMSComment(Kind, ArgumentString);
931252723Sdim}
932