aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Lex/PPMacroExpansion.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Lex/PPMacroExpansion.cpp')
-rw-r--r--clang/lib/Lex/PPMacroExpansion.cpp144
1 files changed, 117 insertions, 27 deletions
diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp
index f3be2107f985..bbc271e5611e 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -37,8 +37,6 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/None.h"
-#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
@@ -54,6 +52,7 @@
#include <cstddef>
#include <cstring>
#include <ctime>
+#include <optional>
#include <string>
#include <tuple>
#include <utility>
@@ -285,7 +284,8 @@ void Preprocessor::dumpMacroInfo(const IdentifierInfo *II) {
// Dump module macros.
llvm::DenseSet<ModuleMacro*> Active;
- for (auto *MM : State ? State->getActiveModuleMacros(*this, II) : None)
+ for (auto *MM :
+ State ? State->getActiveModuleMacros(*this, II) : std::nullopt)
Active.insert(MM);
llvm::DenseSet<ModuleMacro*> Visited;
llvm::SmallVector<ModuleMacro *, 16> Worklist(Leaf.begin(), Leaf.end());
@@ -371,6 +371,8 @@ void Preprocessor::RegisterBuiltinMacros() {
Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature");
Ident__has_extension = RegisterBuiltinMacro(*this, "__has_extension");
Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin");
+ Ident__has_constexpr_builtin =
+ RegisterBuiltinMacro(*this, "__has_constexpr_builtin");
Ident__has_attribute = RegisterBuiltinMacro(*this, "__has_attribute");
if (!getLangOpts().CPlusPlus)
Ident__has_c_attribute = RegisterBuiltinMacro(*this, "__has_c_attribute");
@@ -387,6 +389,10 @@ void Preprocessor::RegisterBuiltinMacros() {
Ident__is_target_os = RegisterBuiltinMacro(*this, "__is_target_os");
Ident__is_target_environment =
RegisterBuiltinMacro(*this, "__is_target_environment");
+ Ident__is_target_variant_os =
+ RegisterBuiltinMacro(*this, "__is_target_variant_os");
+ Ident__is_target_variant_environment =
+ RegisterBuiltinMacro(*this, "__is_target_variant_environment");
// Modules.
Ident__building_module = RegisterBuiltinMacro(*this, "__building_module");
@@ -1081,8 +1087,15 @@ void Preprocessor::removeCachedMacroExpandedTokensOfLastLexer() {
/// the identifier tokens inserted.
static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc,
Preprocessor &PP) {
- time_t TT = time(nullptr);
- struct tm *TM = localtime(&TT);
+ time_t TT;
+ std::tm *TM;
+ if (PP.getPreprocessorOpts().SourceDateEpoch) {
+ TT = *PP.getPreprocessorOpts().SourceDateEpoch;
+ TM = std::gmtime(&TT);
+ } else {
+ TT = std::time(nullptr);
+ TM = std::localtime(&TT);
+ }
static const char * const Months[] = {
"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
@@ -1091,8 +1104,11 @@ static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc,
{
SmallString<32> TmpBuffer;
llvm::raw_svector_ostream TmpStream(TmpBuffer);
- TmpStream << llvm::format("\"%s %2d %4d\"", Months[TM->tm_mon],
- TM->tm_mday, TM->tm_year + 1900);
+ if (TM)
+ TmpStream << llvm::format("\"%s %2d %4d\"", Months[TM->tm_mon],
+ TM->tm_mday, TM->tm_year + 1900);
+ else
+ TmpStream << "??? ?? ????";
Token TmpTok;
TmpTok.startToken();
PP.CreateString(TmpStream.str(), TmpTok);
@@ -1102,8 +1118,11 @@ static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc,
{
SmallString<32> TmpBuffer;
llvm::raw_svector_ostream TmpStream(TmpBuffer);
- TmpStream << llvm::format("\"%02d:%02d:%02d\"",
- TM->tm_hour, TM->tm_min, TM->tm_sec);
+ if (TM)
+ TmpStream << llvm::format("\"%02d:%02d:%02d\"", TM->tm_hour, TM->tm_min,
+ TM->tm_sec);
+ else
+ TmpStream << "??:??:??";
Token TmpTok;
TmpTok.startToken();
PP.CreateString(TmpStream.str(), TmpTok);
@@ -1230,7 +1249,7 @@ static bool EvaluateHasIncludeCommon(Token &Tok, IdentifierInfo *II,
return false;
// Search include directories.
- Optional<FileEntryRef> File =
+ OptionalFileEntryRef File =
PP.LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, LookupFromFile,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
@@ -1282,7 +1301,7 @@ static void EvaluateFeatureLikeBuiltinMacro(llvm::raw_svector_ostream& OS,
unsigned ParenDepth = 1;
SourceLocation LParenLoc = Tok.getLocation();
- llvm::Optional<int> Result;
+ std::optional<int> Result;
Token ResultTok;
bool SuppressDiagnostic = false;
@@ -1326,10 +1345,10 @@ already_lexed:
// The last ')' has been reached; return the value if one found or
// a diagnostic and a dummy value.
if (Result) {
- OS << Result.value();
+ OS << *Result;
// For strict conformance to __has_cpp_attribute rules, use 'L'
// suffix for dated literals.
- if (Result.value() > 1)
+ if (*Result > 1)
OS << 'L';
} else {
OS << 0;
@@ -1428,9 +1447,47 @@ static bool isTargetEnvironment(const TargetInfo &TI,
const IdentifierInfo *II) {
std::string EnvName = (llvm::Twine("---") + II->getName().lower()).str();
llvm::Triple Env(EnvName);
+ // The unknown environment is matched only if
+ // '__is_target_environment(unknown)' is used.
+ if (Env.getEnvironment() == llvm::Triple::UnknownEnvironment &&
+ EnvName != "---unknown")
+ return false;
return TI.getTriple().getEnvironment() == Env.getEnvironment();
}
+/// Implements the __is_target_variant_os builtin macro.
+static bool isTargetVariantOS(const TargetInfo &TI, const IdentifierInfo *II) {
+ if (TI.getTriple().isOSDarwin()) {
+ const llvm::Triple *VariantTriple = TI.getDarwinTargetVariantTriple();
+ if (!VariantTriple)
+ return false;
+
+ 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 VariantTriple->isOSDarwin();
+ }
+ return VariantTriple->getOS() == OS.getOS();
+ }
+ return false;
+}
+
+/// Implements the __is_target_variant_environment builtin macro.
+static bool isTargetVariantEnvironment(const TargetInfo &TI,
+ const IdentifierInfo *II) {
+ if (TI.getTriple().isOSDarwin()) {
+ const llvm::Triple *VariantTriple = TI.getDarwinTargetVariantTriple();
+ if (!VariantTriple)
+ return false;
+ std::string EnvName = (llvm::Twine("---") + II->getName().lower()).str();
+ llvm::Triple Env(EnvName);
+ return VariantTriple->getEnvironment() == Env.getEnvironment();
+ }
+ return false;
+}
+
/// 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) {
@@ -1556,22 +1613,24 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
Diag(Tok.getLocation(), diag::warn_pp_date_time);
// MSVC, ICC, GCC, VisualAge C++ extension. The generated string should be
// of the form "Ddd Mmm dd hh::mm::ss yyyy", which is returned by asctime.
-
- // Get the file that we are lexing out of. If we're currently lexing from
- // a macro, dig into the include stack.
- const FileEntry *CurFile = nullptr;
- PreprocessorLexer *TheLexer = getCurrentFileLexer();
-
- if (TheLexer)
- CurFile = SourceMgr.getFileEntryForID(TheLexer->getFileID());
-
const char *Result;
- if (CurFile) {
- time_t TT = CurFile->getModificationTime();
- struct tm *TM = localtime(&TT);
+ if (getPreprocessorOpts().SourceDateEpoch) {
+ time_t TT = *getPreprocessorOpts().SourceDateEpoch;
+ std::tm *TM = std::gmtime(&TT);
Result = asctime(TM);
} else {
- Result = "??? ??? ?? ??:??:?? ????\n";
+ // Get the file that we are lexing out of. If we're currently lexing from
+ // a macro, dig into the include stack.
+ const FileEntry *CurFile = nullptr;
+ if (PreprocessorLexer *TheLexer = getCurrentFileLexer())
+ CurFile = SourceMgr.getFileEntryForID(TheLexer->getFileID());
+ if (CurFile) {
+ time_t TT = CurFile->getModificationTime();
+ struct tm *TM = localtime(&TT);
+ Result = asctime(TM);
+ } else {
+ Result = "??? ??? ?? ??:??:?? ????\n";
+ }
}
// Surround the string with " and strip the trailing newline.
OS << '"' << StringRef(Result).drop_back() << '"';
@@ -1663,7 +1722,8 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
.Case("__array_rank", true)
.Case("__array_extent", true)
.Case("__reference_binds_to_temporary", true)
- .Case("__underlying_type", true)
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) .Case("__" #Trait, true)
+#include "clang/Basic/TransformTypeTraits.def"
.Default(false);
} else {
return llvm::StringSwitch<bool>(II->getName())
@@ -1677,9 +1737,23 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
.Case("__is_target_vendor", true)
.Case("__is_target_os", true)
.Case("__is_target_environment", true)
+ .Case("__is_target_variant_os", true)
+ .Case("__is_target_variant_environment", true)
.Default(false);
}
});
+ } else if (II == Ident__has_constexpr_builtin) {
+ EvaluateFeatureLikeBuiltinMacro(
+ OS, Tok, II, *this, false,
+ [this](Token &Tok, bool &HasLexedNextToken) -> int {
+ IdentifierInfo *II = ExpectFeatureIdentifierInfo(
+ Tok, *this, diag::err_feature_check_malformed);
+ if (!II)
+ return false;
+ unsigned BuiltinOp = II->getBuiltinID();
+ return BuiltinOp != 0 &&
+ this->getBuiltinInfo().isConstantEvaluated(BuiltinOp);
+ });
} else if (II == Ident__is_identifier) {
EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, false,
[](Token &Tok, bool &HasLexedNextToken) -> int {
@@ -1877,6 +1951,22 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
Tok, *this, diag::err_feature_check_malformed);
return II && isTargetEnvironment(getTargetInfo(), II);
});
+ } else if (II == Ident__is_target_variant_os) {
+ EvaluateFeatureLikeBuiltinMacro(
+ OS, Tok, II, *this, false,
+ [this](Token &Tok, bool &HasLexedNextToken) -> int {
+ IdentifierInfo *II = ExpectFeatureIdentifierInfo(
+ Tok, *this, diag::err_feature_check_malformed);
+ return II && isTargetVariantOS(getTargetInfo(), II);
+ });
+ } else if (II == Ident__is_target_variant_environment) {
+ EvaluateFeatureLikeBuiltinMacro(
+ OS, Tok, II, *this, false,
+ [this](Token &Tok, bool &HasLexedNextToken) -> int {
+ IdentifierInfo *II = ExpectFeatureIdentifierInfo(
+ Tok, *this, diag::err_feature_check_malformed);
+ return II && isTargetVariantEnvironment(getTargetInfo(), II);
+ });
} else {
llvm_unreachable("Unknown identifier!");
}