1c383a500aa59423264811be3874461bf8adbfea0Zonr Chang/*
2c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Copyright 2010, The Android Open Source Project
3c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
4c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Licensed under the Apache License, Version 2.0 (the "License");
5c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * you may not use this file except in compliance with the License.
6c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * You may obtain a copy of the License at
7c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
8c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *     http://www.apache.org/licenses/LICENSE-2.0
9c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
10c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Unless required by applicable law or agreed to in writing, software
11c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * distributed under the License is distributed on an "AS IS" BASIS,
12c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * See the License for the specific language governing permissions and
14c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * limitations under the License.
15c383a500aa59423264811be3874461bf8adbfea0Zonr Chang */
16c383a500aa59423264811be3874461bf8adbfea0Zonr Chang
176315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr#include "slang_rs_pragma_handler.h"
18462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
193fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines#include <sstream>
20e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include <string>
21e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
229ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao#include "clang/Basic/TokenKinds.h"
23462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
249ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao#include "clang/Lex/LiteralSupport.h"
259ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao#include "clang/Lex/Preprocessor.h"
269ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao#include "clang/Lex/Token.h"
27462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
286e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines#include "slang_assert.h"
296315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr#include "slang_rs_context.h"
306315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr
31e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesnamespace slang {
32462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
339ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liaonamespace {  // Anonymous namespace
34462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
35462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liaoclass RSExportTypePragmaHandler : public RSPragmaHandler {
369ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao private:
376315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr  void handleItem(const std::string &Item) {
383fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines    mContext->addPragma(this->getName(), Item);
399ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    mContext->addExportType(Item);
409ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
419ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
429ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao public:
436315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr  RSExportTypePragmaHandler(llvm::StringRef Name, RSContext *Context)
44796e7b1400d3f3f7c07496d88bb48129ea925bb9Jean-Luc Brouillet      : RSPragmaHandler(Name, Context) { }
459ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
46df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao  void HandlePragma(clang::Preprocessor &PP,
47df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao                    clang::PragmaIntroducerKind Introducer,
48df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao                    clang::Token &FirstToken) {
499ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    this->handleItemListPragma(PP, FirstToken);
509ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
51462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao};
52462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
53537446c9542fdda458920876ed8a020a97ddf7a4Shih-wei Liaoclass RSJavaPackageNamePragmaHandler : public RSPragmaHandler {
549ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao public:
556315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr  RSJavaPackageNamePragmaHandler(llvm::StringRef Name, RSContext *Context)
56796e7b1400d3f3f7c07496d88bb48129ea925bb9Jean-Luc Brouillet      : RSPragmaHandler(Name, Context) { }
579ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
58df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao  void HandlePragma(clang::Preprocessor &PP,
59df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao                    clang::PragmaIntroducerKind Introducer,
60df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao                    clang::Token &FirstToken) {
6135f5b39f0490953f1fe13ef803b43e3ced9a01d9Stephen Hines    // FIXME: Need to validate the extracted package name from pragma.
629ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // Currently "all chars" specified in pragma will be treated as package
639ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // name.
649ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //
659ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // 18.1 The Grammar of the Java Programming Language
669ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // (http://java.sun.com/docs/books/jls/third_edition/html/syntax.html#18.1)
679ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //
689ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // CompilationUnit:
699ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //     [[Annotations] package QualifiedIdentifier   ;  ] {ImportDeclaration}
709ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //     {TypeDeclaration}
719ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //
729ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // QualifiedIdentifier:
739ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //     Identifier { . Identifier }
749ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //
759ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // Identifier:
769ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //     IDENTIFIER
779ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //
789ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // 3.8 Identifiers
799ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // (http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.8)
809ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //
819ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //
829ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
839ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    clang::Token &PragmaToken = FirstToken;
849ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    std::string PackageName;
859ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
869ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // Skip first token, "java_package_name"
879ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    PP.LexUnexpandedToken(PragmaToken);
88537446c9542fdda458920876ed8a020a97ddf7a4Shih-wei Liao
899ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // Now, the current token must be clang::tok::lpara
909ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    if (PragmaToken.isNot(clang::tok::l_paren))
919ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      return;
929ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
93be27482cdeaf08576bc39b72a15d35d13014a636Logan    while (PragmaToken.isNot(clang::tok::eod)) {
949ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      // Lex package name
959ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      PP.LexUnexpandedToken(PragmaToken);
969ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
979ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      bool Invalid;
989ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      std::string Spelling = PP.getSpelling(PragmaToken, &Invalid);
999ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      if (!Invalid)
1009ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        PackageName.append(Spelling);
1019ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
1029ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      // Pre-mature end (syntax error will be triggered by preprocessor later)
103be27482cdeaf08576bc39b72a15d35d13014a636Logan      if (PragmaToken.is(clang::tok::eod) || PragmaToken.is(clang::tok::eof)) {
1049ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        break;
1056315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr      } else {
10696ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines        // Next token is ')' (end of pragma)
1079ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        const clang::Token &NextTok = PP.LookAhead(0);
1089ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        if (NextTok.is(clang::tok::r_paren)) {
1093fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines          mContext->addPragma(this->getName(), PackageName);
1109ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao          mContext->setReflectJavaPackageName(PackageName);
111be27482cdeaf08576bc39b72a15d35d13014a636Logan          // Lex until meets clang::tok::eod
1129ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao          do {
1139ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao            PP.LexUnexpandedToken(PragmaToken);
114be27482cdeaf08576bc39b72a15d35d13014a636Logan          } while (PragmaToken.isNot(clang::tok::eod));
1159ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao          break;
116537446c9542fdda458920876ed8a020a97ddf7a4Shih-wei Liao        }
1179ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      }
118537446c9542fdda458920876ed8a020a97ddf7a4Shih-wei Liao    }
1199ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
120537446c9542fdda458920876ed8a020a97ddf7a4Shih-wei Liao};
121537446c9542fdda458920876ed8a020a97ddf7a4Shih-wei Liao
122d8a0d186a362739f385f1a4af35360d5da69e47bVictor Hsiehclass RSReflectLicensePragmaHandler : public RSPragmaHandler {
1239ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao private:
1249ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  void handleItem(const std::string &Item) {
1253fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines    mContext->addPragma(this->getName(), Item);
1269ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    mContext->setLicenseNote(Item);
1279ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
1289ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
1299ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao public:
1309ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  RSReflectLicensePragmaHandler(llvm::StringRef Name, RSContext *Context)
131796e7b1400d3f3f7c07496d88bb48129ea925bb9Jean-Luc Brouillet      : RSPragmaHandler(Name, Context) { }
1329ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
133df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao  void HandlePragma(clang::Preprocessor &PP,
134df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao                    clang::PragmaIntroducerKind Introducer,
135df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao                    clang::Token &FirstToken) {
1369d2c0fa6490e09b3ff5603796bce42d97788e5c8Stephen Hines    this->handleOptionalStringLiteralParamPragma(PP, FirstToken);
1379ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
138d8a0d186a362739f385f1a4af35360d5da69e47bVictor Hsieh};
139d8a0d186a362739f385f1a4af35360d5da69e47bVictor Hsieh
14096ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hinesclass RSVersionPragmaHandler : public RSPragmaHandler {
14196ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines private:
1427aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines  void handleInt(clang::Preprocessor &PP,
1437aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines                 clang::Token &Tok,
1447aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines                 const int v) {
1457aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    if (v != 1) {
1467aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      PP.Diag(Tok,
1477aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines              PP.getDiagnostics().getCustomDiagID(
1487aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines                  clang::DiagnosticsEngine::Error,
1497aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines                  "pragma for version in source file must be set to 1"));
1507aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      mContext->setVersion(1);
1517aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      return;
1527aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    }
1533fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines    std::stringstream ss;
1543fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines    ss << v;
1553fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines    mContext->addPragma(this->getName(), ss.str());
15696ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    mContext->setVersion(v);
15796ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  }
15896ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
15996ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines public:
16096ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  RSVersionPragmaHandler(llvm::StringRef Name, RSContext *Context)
161796e7b1400d3f3f7c07496d88bb48129ea925bb9Jean-Luc Brouillet      : RSPragmaHandler(Name, Context) { }
16296ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
163df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao  void HandlePragma(clang::Preprocessor &PP,
164df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao                    clang::PragmaIntroducerKind Introducer,
165df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao                    clang::Token &FirstToken) {
16696ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    this->handleIntegerParamPragma(PP, FirstToken);
16796ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  }
16896ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines};
16996ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
170109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet// Handles the pragmas rs_fp_full, rs_fp_relaxed, and rs_fp_imprecise.
171109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet// There's one instance of this handler for each of the above values.
172109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet// Only getName() differs between the instances.
173109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouilletclass RSPrecisionPragmaHandler : public RSPragmaHandler {
174109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouilletpublic:
175109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  RSPrecisionPragmaHandler(llvm::StringRef Name, RSContext *Context)
176109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet      : RSPragmaHandler(Name, Context) {}
177462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
178109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  void HandlePragma(clang::Preprocessor &PP,
179109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet                    clang::PragmaIntroducerKind Introducer,
180109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet                    clang::Token &Token) {
181109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet    std::string Precision = getName();
182109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet    // We are deprecating rs_fp_imprecise.
183109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet    if (Precision == "rs_fp_imprecise") {
184109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet      PP.Diag(Token, PP.getDiagnostics().getCustomDiagID(
185109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet                         clang::DiagnosticsEngine::Warning,
186109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet                         "rs_fp_imprecise is deprecated.  Assuming "
187109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet                         "rs_fp_relaxed instead."));
188109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet      Precision = "rs_fp_relaxed";
189109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet    }
190109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet    // Check if we have already encountered a precision pragma already.
191109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet    std::string PreviousPrecision = mContext->getPrecision();
192109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet    if (!PreviousPrecision.empty()) {
193109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet      // If the previous specified a different value, it's an error.
194109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet      if (PreviousPrecision != Precision) {
195109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet        PP.Diag(Token, PP.getDiagnostics().getCustomDiagID(
196109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet                           clang::DiagnosticsEngine::Error,
197109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet                           "Multiple float precisions specified.  Encountered "
198109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet                           "%0 previously."))
199109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet            << PreviousPrecision;
200109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet      }
201109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet      // Otherwise we ignore redundant entries.
202109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet      return;
203109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet    }
204537446c9542fdda458920876ed8a020a97ddf7a4Shih-wei Liao
205109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet    mContext->addPragma(Precision, "");
206109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet    mContext->setPrecision(Precision);
207109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  }
208109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet};
209d8a0d186a362739f385f1a4af35360d5da69e47bVictor Hsieh
210109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet}  // namespace
21196ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
2129ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liaovoid RSPragmaHandler::handleItemListPragma(clang::Preprocessor &PP,
2139ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                           clang::Token &FirstToken) {
2149ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  clang::Token &PragmaToken = FirstToken;
215462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
2169ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Skip first token, like "export_var"
2179ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  PP.LexUnexpandedToken(PragmaToken);
218462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
2199ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Now, the current token must be clang::tok::lpara
2209ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (PragmaToken.isNot(clang::tok::l_paren))
2219ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return;
222462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
223be27482cdeaf08576bc39b72a15d35d13014a636Logan  while (PragmaToken.isNot(clang::tok::eod)) {
2249ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // Lex variable name
2259ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    PP.LexUnexpandedToken(PragmaToken);
2269ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    if (PragmaToken.is(clang::tok::identifier))
2276315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr      this->handleItem(PP.getSpelling(PragmaToken));
2289ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    else
2299ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      break;
230462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
231be27482cdeaf08576bc39b72a15d35d13014a636Logan    slangAssert(PragmaToken.isNot(clang::tok::eod));
232462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
2339ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    PP.LexUnexpandedToken(PragmaToken);
234462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
2359ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    if (PragmaToken.isNot(clang::tok::comma))
2369ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      break;
2379ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
238462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
239462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
2406315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonrvoid RSPragmaHandler::handleNonParamPragma(clang::Preprocessor &PP,
2416315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr                                           clang::Token &FirstToken) {
2426315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr  clang::Token &PragmaToken = FirstToken;
243c6718b312b793ea76ac6b61479090c33ba9f2ba6Victor Hsieh
2449ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Skip first token, like "export_var_all"
2459ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  PP.LexUnexpandedToken(PragmaToken);
246c6718b312b793ea76ac6b61479090c33ba9f2ba6Victor Hsieh
2479ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Should be end immediately
248be27482cdeaf08576bc39b72a15d35d13014a636Logan  if (PragmaToken.isNot(clang::tok::eod))
2497aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    if (PragmaToken.isNot(clang::tok::r_paren)) {
2507aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      PP.Diag(PragmaToken,
2517aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines              PP.getDiagnostics().getCustomDiagID(
2527aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines                  clang::DiagnosticsEngine::Error,
2537aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines                  "expected a ')'"));
2547aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      return;
2557aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    }
256c6718b312b793ea76ac6b61479090c33ba9f2ba6Victor Hsieh}
257c6718b312b793ea76ac6b61479090c33ba9f2ba6Victor Hsieh
2589d2c0fa6490e09b3ff5603796bce42d97788e5c8Stephen Hinesvoid RSPragmaHandler::handleOptionalStringLiteralParamPragma(
2599ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    clang::Preprocessor &PP, clang::Token &FirstToken) {
2609ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  clang::Token &PragmaToken = FirstToken;
261d8a0d186a362739f385f1a4af35360d5da69e47bVictor Hsieh
2629ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Skip first token, like "set_reflect_license"
2639ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  PP.LexUnexpandedToken(PragmaToken);
264d8a0d186a362739f385f1a4af35360d5da69e47bVictor Hsieh
2659ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Now, the current token must be clang::tok::lpara
2669ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (PragmaToken.isNot(clang::tok::l_paren))
2679ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return;
268d8a0d186a362739f385f1a4af35360d5da69e47bVictor Hsieh
2699ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // If not ')', eat the following string literal as the license
2709ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  PP.LexUnexpandedToken(PragmaToken);
2719ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (PragmaToken.isNot(clang::tok::r_paren)) {
2729ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // Eat the whole string literal
2732eb9a3f7c48fe54eb4e813d80e3363bc79553a1eStephen Hines    clang::StringLiteralParser StringLiteral(PragmaToken, PP);
2747aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    if (StringLiteral.hadError) {
2757aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      // Diagnostics will be generated automatically
2767aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      return;
277e67239de8d94975e7e2216ee6860ae2e6cb8b15aStephen Hines    } else {
2786315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr      this->handleItem(std::string(StringLiteral.GetString()));
2797aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    }
2809ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
2819ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // The current token should be clang::tok::r_para
282d8a0d186a362739f385f1a4af35360d5da69e47bVictor Hsieh    PP.LexUnexpandedToken(PragmaToken);
2837aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    if (PragmaToken.isNot(clang::tok::r_paren)) {
2847aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      PP.Diag(PragmaToken,
2857aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines              PP.getDiagnostics().getCustomDiagID(
2867aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines                  clang::DiagnosticsEngine::Error,
2877aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines                  "expected a ')'"));
2887aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      return;
2897aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    }
2909ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  } else {
2919ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // If no argument, remove the license
2926315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr    this->handleItem("");
2939ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
294d8a0d186a362739f385f1a4af35360d5da69e47bVictor Hsieh}
295e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
29696ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hinesvoid RSPragmaHandler::handleIntegerParamPragma(
29796ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    clang::Preprocessor &PP, clang::Token &FirstToken) {
29896ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  clang::Token &PragmaToken = FirstToken;
29996ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
30096ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  // Skip first token, like "version"
30196ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  PP.LexUnexpandedToken(PragmaToken);
30296ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
30396ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  // Now, the current token must be clang::tok::lpara
3047aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines  if (PragmaToken.isNot(clang::tok::l_paren)) {
3057aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    // If no argument, set the version to 0
3067aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    this->handleInt(PP, PragmaToken, 0);
30796ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    return;
3087aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines  }
30996ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  PP.LexUnexpandedToken(PragmaToken);
31096ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
31196ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  if (PragmaToken.is(clang::tok::numeric_constant)) {
31223c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines    llvm::SmallString<128> SpellingBuffer;
31323c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines    SpellingBuffer.resize(PragmaToken.getLength() + 1);
31423c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines    llvm::StringRef TokSpelling = PP.getSpelling(PragmaToken, SpellingBuffer);
31523c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines    clang::NumericLiteralParser NumericLiteral(TokSpelling,
31696ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines        PragmaToken.getLocation(), PP);
31796ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    if (NumericLiteral.hadError) {
3187aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      // Diagnostics will be generated automatically
3197aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      return;
32096ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    } else {
32196ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines      llvm::APInt Val(32, 0);
32296ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines      NumericLiteral.GetIntegerValue(Val);
3237aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      this->handleInt(PP, PragmaToken, static_cast<int>(Val.getSExtValue()));
32496ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    }
32596ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    PP.LexUnexpandedToken(PragmaToken);
32696ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  } else {
32796ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    // If no argument, set the version to 0
3287aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    this->handleInt(PP, PragmaToken, 0);
32996ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  }
33096ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
33196ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  if (PragmaToken.isNot(clang::tok::r_paren)) {
3327aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    PP.Diag(PragmaToken,
3337aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines            PP.getDiagnostics().getCustomDiagID(
3347aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines                clang::DiagnosticsEngine::Error,
3357aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines                "expected a ')'"));
3367aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    return;
33796ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  }
33896ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
33996ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  do {
34096ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    PP.LexUnexpandedToken(PragmaToken);
341be27482cdeaf08576bc39b72a15d35d13014a636Logan  } while (PragmaToken.isNot(clang::tok::eod));
34296ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines}
34396ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
344109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouilletvoid AddPragmaHandlers(clang::Preprocessor &PP, RSContext *RsContext) {
345109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  // For #pragma rs export_type
346109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  PP.AddPragmaHandler("rs",
347109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet                      new RSExportTypePragmaHandler("export_type", RsContext));
348109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet
349109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  // For #pragma rs java_package_name
350109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  PP.AddPragmaHandler(
351109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet      "rs", new RSJavaPackageNamePragmaHandler("java_package_name", RsContext));
352109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet
353109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  // For #pragma rs set_reflect_license
354109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  PP.AddPragmaHandler(
355109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet      "rs", new RSReflectLicensePragmaHandler("set_reflect_license", RsContext));
356109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet
357109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  // For #pragma version
358109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  PP.AddPragmaHandler(new RSVersionPragmaHandler("version", RsContext));
359109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet
360109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  // For #pragma rs_fp*
361109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  PP.AddPragmaHandler(new RSPrecisionPragmaHandler("rs_fp_full", RsContext));
362109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  PP.AddPragmaHandler(new RSPrecisionPragmaHandler("rs_fp_relaxed", RsContext));
363109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  PP.AddPragmaHandler(new RSPrecisionPragmaHandler("rs_fp_imprecise", RsContext));
364109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet}
365109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet
366109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet
367e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines}  // namespace slang
368