diff options
Diffstat (limited to 'lib/Lex/PPMacroExpansion.cpp')
| -rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 144 | 
1 files changed, 120 insertions, 24 deletions
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 3f8ede23da56..41633f90c34d 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -369,11 +369,17 @@ void Preprocessor::RegisterBuiltinMacros() {    Ident__has_extension    = RegisterBuiltinMacro(*this, "__has_extension");    Ident__has_builtin      = RegisterBuiltinMacro(*this, "__has_builtin");    Ident__has_attribute    = RegisterBuiltinMacro(*this, "__has_attribute"); +  Ident__has_c_attribute  = RegisterBuiltinMacro(*this, "__has_c_attribute");    Ident__has_declspec = RegisterBuiltinMacro(*this, "__has_declspec_attribute");    Ident__has_include      = RegisterBuiltinMacro(*this, "__has_include");    Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next");    Ident__has_warning      = RegisterBuiltinMacro(*this, "__has_warning");    Ident__is_identifier    = RegisterBuiltinMacro(*this, "__is_identifier"); +  Ident__is_target_arch   = RegisterBuiltinMacro(*this, "__is_target_arch"); +  Ident__is_target_vendor = RegisterBuiltinMacro(*this, "__is_target_vendor"); +  Ident__is_target_os     = RegisterBuiltinMacro(*this, "__is_target_os"); +  Ident__is_target_environment = +      RegisterBuiltinMacro(*this, "__is_target_environment");    // Modules.    Ident__building_module  = RegisterBuiltinMacro(*this, "__building_module"); @@ -1023,7 +1029,7 @@ Token *Preprocessor::cacheMacroExpandedTokens(TokenLexer *tokLexer,    size_t newIndex = MacroExpandedTokens.size();    bool cacheNeedsToGrow = tokens.size() > -                      MacroExpandedTokens.capacity()-MacroExpandedTokens.size();  +                      MacroExpandedTokens.capacity()-MacroExpandedTokens.size();    MacroExpandedTokens.append(tokens.begin(), tokens.end());    if (cacheNeedsToGrow) { @@ -1098,6 +1104,8 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) {        .Case("address_sanitizer",              LangOpts.Sanitize.hasOneOf(SanitizerKind::Address |                                         SanitizerKind::KernelAddress)) +      .Case("hwaddress_sanitizer", +            LangOpts.Sanitize.hasOneOf(SanitizerKind::HWAddress))        .Case("assume_nonnull", true)        .Case("attribute_analyzer_noreturn", true)        .Case("attribute_availability", true) @@ -1135,9 +1143,11 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) {        .Case("nullability_on_arrays", true)        .Case("memory_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Memory))        .Case("thread_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Thread)) -      .Case("dataflow_sanitizer", LangOpts.Sanitize.has(SanitizerKind::DataFlow)) +      .Case("dataflow_sanitizer", +            LangOpts.Sanitize.has(SanitizerKind::DataFlow))        .Case("efficiency_sanitizer",              LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency)) +      .Case("scudo", LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo))        // Objective-C features        .Case("objc_arr", LangOpts.ObjCAutoRefCount) // FIXME: REMOVE?        .Case("objc_arc", LangOpts.ObjCAutoRefCount) @@ -1588,6 +1598,56 @@ static IdentifierInfo *ExpectFeatureIdentifierInfo(Token &Tok,    return nullptr;  } +/// Implements the __is_target_arch builtin macro. +static bool isTargetArch(const TargetInfo &TI, const IdentifierInfo *II) { +  std::string ArchName = II->getName().lower() + "--"; +  llvm::Triple Arch(ArchName); +  const llvm::Triple &TT = TI.getTriple(); +  if (TT.isThumb()) { +    // arm matches thumb or thumbv7. armv7 matches thumbv7. +    if ((Arch.getSubArch() == llvm::Triple::NoSubArch || +         Arch.getSubArch() == TT.getSubArch()) && +        ((TT.getArch() == llvm::Triple::thumb && +          Arch.getArch() == llvm::Triple::arm) || +         (TT.getArch() == llvm::Triple::thumbeb && +          Arch.getArch() == llvm::Triple::armeb))) +      return true; +  } +  // Check the parsed arch when it has no sub arch to allow Clang to +  // match thumb to thumbv7 but to prohibit matching thumbv6 to thumbv7. +  return (Arch.getSubArch() == llvm::Triple::NoSubArch || +          Arch.getSubArch() == TT.getSubArch()) && +         Arch.getArch() == TT.getArch(); +} + +/// Implements the __is_target_vendor builtin macro. +static bool isTargetVendor(const TargetInfo &TI, const IdentifierInfo *II) { +  StringRef VendorName = TI.getTriple().getVendorName(); +  if (VendorName.empty()) +    VendorName = "unknown"; +  return VendorName.equals_lower(II->getName()); +} + +/// Implements the __is_target_os builtin macro. +static bool isTargetOS(const TargetInfo &TI, const IdentifierInfo *II) { +  std::string OSName = +      (llvm::Twine("unknown-unknown-") + II->getName().lower()).str(); +  llvm::Triple OS(OSName); +  if (OS.getOS() == llvm::Triple::Darwin) { +    // Darwin matches macos, ios, etc. +    return TI.getTriple().isOSDarwin(); +  } +  return TI.getTriple().getOS() == OS.getOS(); +} + +/// Implements the __is_target_environment builtin macro. +static bool isTargetEnvironment(const TargetInfo &TI, +                                const IdentifierInfo *II) { +  std::string EnvName = (llvm::Twine("---") + II->getName().lower()).str(); +  llvm::Triple Env(EnvName); +  return TI.getTriple().getEnvironment() == Env.getEnvironment(); +} +  /// ExpandBuiltinMacro - If an identifier token is read that is to be expanded  /// as a builtin macro, handle it and return the next token as 'Tok'.  void Preprocessor::ExpandBuiltinMacro(Token &Tok) { @@ -1750,6 +1810,10 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {                        .Case("__make_integer_seq", LangOpts.CPlusPlus)                        .Case("__type_pack_element", LangOpts.CPlusPlus)                        .Case("__builtin_available", true) +                      .Case("__is_target_arch", true) +                      .Case("__is_target_vendor", true) +                      .Case("__is_target_os", true) +                      .Case("__is_target_environment", true)                        .Default(false);          }        }); @@ -1774,30 +1838,34 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {          return II ? hasAttribute(AttrSyntax::Declspec, nullptr, II,                                   getTargetInfo(), getLangOpts()) : 0;        }); -  } else if (II == Ident__has_cpp_attribute) { -    EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, -      [this](Token &Tok, bool &HasLexedNextToken) -> int { -        IdentifierInfo *ScopeII = nullptr; -        IdentifierInfo *II = ExpectFeatureIdentifierInfo(Tok, *this, -                                           diag::err_feature_check_malformed); -        if (!II) -          return false; - -        // It is possible to receive a scope token.  Read the "::", if it is -        // available, and the subsequent identifier. -        LexUnexpandedToken(Tok); -        if (Tok.isNot(tok::coloncolon)) -          HasLexedNextToken = true; -        else { -          ScopeII = II; +  } else if (II == Ident__has_cpp_attribute || +             II == Ident__has_c_attribute) { +    bool IsCXX = II == Ident__has_cpp_attribute; +    EvaluateFeatureLikeBuiltinMacro( +        OS, Tok, II, *this, [&](Token &Tok, bool &HasLexedNextToken) -> int { +          IdentifierInfo *ScopeII = nullptr; +          IdentifierInfo *II = ExpectFeatureIdentifierInfo( +              Tok, *this, diag::err_feature_check_malformed); +          if (!II) +            return false; + +          // It is possible to receive a scope token.  Read the "::", if it is +          // available, and the subsequent identifier.            LexUnexpandedToken(Tok); -          II = ExpectFeatureIdentifierInfo(Tok, *this, -                                           diag::err_feature_check_malformed); -        } +          if (Tok.isNot(tok::coloncolon)) +            HasLexedNextToken = true; +          else { +            ScopeII = II; +            LexUnexpandedToken(Tok); +            II = ExpectFeatureIdentifierInfo(Tok, *this, +                                             diag::err_feature_check_malformed); +          } -        return II ? hasAttribute(AttrSyntax::CXX, ScopeII, II, -                                 getTargetInfo(), getLangOpts()) : 0; -      }); +          AttrSyntax Syntax = IsCXX ? AttrSyntax::CXX : AttrSyntax::C; +          return II ? hasAttribute(Syntax, ScopeII, II, getTargetInfo(), +                                   getLangOpts()) +                    : 0; +        });    } else if (II == Ident__has_include ||               II == Ident__has_include_next) {      // The argument to these two builtins should be a parenthesized @@ -1897,6 +1965,34 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {        Diag(LParenLoc, diag::note_matching) << tok::l_paren;      }      return; +  } else if (II == Ident__is_target_arch) { +    EvaluateFeatureLikeBuiltinMacro( +        OS, Tok, II, *this, [this](Token &Tok, bool &HasLexedNextToken) -> int { +          IdentifierInfo *II = ExpectFeatureIdentifierInfo( +              Tok, *this, diag::err_feature_check_malformed); +          return II && isTargetArch(getTargetInfo(), II); +        }); +  } else if (II == Ident__is_target_vendor) { +    EvaluateFeatureLikeBuiltinMacro( +        OS, Tok, II, *this, [this](Token &Tok, bool &HasLexedNextToken) -> int { +          IdentifierInfo *II = ExpectFeatureIdentifierInfo( +              Tok, *this, diag::err_feature_check_malformed); +          return II && isTargetVendor(getTargetInfo(), II); +        }); +  } else if (II == Ident__is_target_os) { +    EvaluateFeatureLikeBuiltinMacro( +        OS, Tok, II, *this, [this](Token &Tok, bool &HasLexedNextToken) -> int { +          IdentifierInfo *II = ExpectFeatureIdentifierInfo( +              Tok, *this, diag::err_feature_check_malformed); +          return II && isTargetOS(getTargetInfo(), II); +        }); +  } else if (II == Ident__is_target_environment) { +    EvaluateFeatureLikeBuiltinMacro( +        OS, Tok, II, *this, [this](Token &Tok, bool &HasLexedNextToken) -> int { +          IdentifierInfo *II = ExpectFeatureIdentifierInfo( +              Tok, *this, diag::err_feature_check_malformed); +          return II && isTargetEnvironment(getTargetInfo(), II); +        });    } else {      llvm_unreachable("Unknown identifier!");    }  | 
