summaryrefslogtreecommitdiff
path: root/lib/Basic
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Basic')
-rw-r--r--lib/Basic/Builtins.cpp18
-rw-r--r--lib/Basic/CMakeLists.txt11
-rw-r--r--lib/Basic/ConvertUTF.c606
-rw-r--r--lib/Basic/Diagnostic.cpp121
-rw-r--r--lib/Basic/FileManager.cpp88
-rw-r--r--lib/Basic/IdentifierTable.cpp58
-rw-r--r--lib/Basic/Makefile11
-rw-r--r--lib/Basic/SourceLocation.cpp4
-rw-r--r--lib/Basic/SourceManager.cpp302
-rw-r--r--lib/Basic/TargetInfo.cpp57
-rw-r--r--lib/Basic/Targets.cpp1092
-rw-r--r--lib/Basic/Version.cpp49
12 files changed, 1544 insertions, 873 deletions
diff --git a/lib/Basic/Builtins.cpp b/lib/Basic/Builtins.cpp
index 6cb5dab53df24..1a3293775ed61 100644
--- a/lib/Basic/Builtins.cpp
+++ b/lib/Basic/Builtins.cpp
@@ -34,7 +34,7 @@ Builtin::Context::Context(const TargetInfo &Target) {
// Get the target specific builtins from the target.
TSRecords = 0;
NumTSRecords = 0;
- Target.getTargetBuiltins(TSRecords, NumTSRecords);
+ Target.getTargetBuiltins(TSRecords, NumTSRecords);
}
/// InitializeBuiltins - Mark the identifiers for all the builtins with their
@@ -51,13 +51,13 @@ void Builtin::Context::InitializeBuiltins(IdentifierTable &Table,
// Step #2: Register target-specific builtins.
for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
if (!TSRecords[i].Suppressed &&
- (!NoBuiltins ||
- (TSRecords[i].Attributes &&
+ (!NoBuiltins ||
+ (TSRecords[i].Attributes &&
!strchr(TSRecords[i].Attributes, 'f'))))
Table.get(TSRecords[i].Name).setBuiltinID(i+Builtin::FirstTSBuiltin);
}
-void
+void
Builtin::Context::GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names,
bool NoBuiltins) {
// Final all target-independent names
@@ -65,18 +65,18 @@ Builtin::Context::GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names,
if (!BuiltinInfo[i].Suppressed &&
(!NoBuiltins || !strchr(BuiltinInfo[i].Attributes, 'f')))
Names.push_back(BuiltinInfo[i].Name);
-
+
// Find target-specific names.
for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
if (!TSRecords[i].Suppressed &&
- (!NoBuiltins ||
- (TSRecords[i].Attributes &&
+ (!NoBuiltins ||
+ (TSRecords[i].Attributes &&
!strchr(TSRecords[i].Attributes, 'f'))))
Names.push_back(TSRecords[i].Name);
}
-bool
-Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx,
+bool
+Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx,
bool &HasVAListArg) {
const char *Printf = strpbrk(GetRecord(ID).Attributes, "pP");
if (!Printf)
diff --git a/lib/Basic/CMakeLists.txt b/lib/Basic/CMakeLists.txt
index e0e9a10e51958..527ebf965934b 100644
--- a/lib/Basic/CMakeLists.txt
+++ b/lib/Basic/CMakeLists.txt
@@ -11,8 +11,19 @@ add_clang_library(clangBasic
TargetInfo.cpp
Targets.cpp
TokenKinds.cpp
+ Version.cpp
)
+# Determine Subversion revision.
+# FIXME: This only gets updated when CMake is run, so this revision number
+# may be out-of-date!
+find_package(Subversion)
+if (Subversion_FOUND)
+ Subversion_WC_INFO(${CLANG_SOURCE_DIR} CLANG)
+ set_source_files_properties(Version.cpp
+ PROPERTIES COMPILE_DEFINITIONS "SVN_REVISION=\"${CLANG_WC_REVISION}\"")
+endif()
+
add_dependencies(clangBasic
ClangDiagnosticAnalysis
ClangDiagnosticAST
diff --git a/lib/Basic/ConvertUTF.c b/lib/Basic/ConvertUTF.c
index e5dd3e6bf5706..124e386c55265 100644
--- a/lib/Basic/ConvertUTF.c
+++ b/lib/Basic/ConvertUTF.c
@@ -34,10 +34,10 @@
Author: Mark E. Davis, 1994.
Rev History: Rick McGowan, fixes & updates May 2001.
Sept 2001: fixed const & error conditions per
- mods suggested by S. Parent & A. Lillich.
+ mods suggested by S. Parent & A. Lillich.
June 2002: Tim Dodd added detection and handling of incomplete
- source sequences, enhanced error detection, added casts
- to eliminate compiler warnings.
+ source sequences, enhanced error detection, added casts
+ to eliminate compiler warnings.
July 2003: slight mods to back out aggressive FFFE detection.
Jan 2004: updated switches in from-UTF8 conversions.
Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
@@ -61,8 +61,8 @@ static const UTF32 halfMask = 0x3FFUL;
#define UNI_SUR_HIGH_END (UTF32)0xDBFF
#define UNI_SUR_LOW_START (UTF32)0xDC00
#define UNI_SUR_LOW_END (UTF32)0xDFFF
-#define false 0
-#define true 1
+#define false 0
+#define true 1
/* --------------------------------------------------------------------- */
@@ -90,7 +90,7 @@ static const char trailingBytesForUTF8[256] = {
* in a UTF-8 sequence.
*/
static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
- 0x03C82080UL, 0xFA082080UL, 0x82082080UL };
+ 0x03C82080UL, 0xFA082080UL, 0x82082080UL };
/*
* Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
@@ -116,46 +116,46 @@ static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF32toUTF16 (
- const UTF32** sourceStart, const UTF32* sourceEnd,
- UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
+ const UTF32** sourceStart, const UTF32* sourceEnd,
+ UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF32* source = *sourceStart;
UTF16* target = *targetStart;
while (source < sourceEnd) {
- UTF32 ch;
- if (target >= targetEnd) {
- result = targetExhausted; break;
- }
- ch = *source++;
- if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
- /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
- if (flags == strictConversion) {
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- *target++ = (UTF16)ch; /* normal case */
- }
- } else if (ch > UNI_MAX_LEGAL_UTF32) {
- if (flags == strictConversion) {
- result = sourceIllegal;
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- /* target is a character in range 0xFFFF - 0x10FFFF. */
- if (target + 1 >= targetEnd) {
- --source; /* Back up source pointer! */
- result = targetExhausted; break;
- }
- ch -= halfBase;
- *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
- *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
- }
+ UTF32 ch;
+ if (target >= targetEnd) {
+ result = targetExhausted; break;
+ }
+ ch = *source++;
+ if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
+ /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ if (flags == strictConversion) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ *target++ = (UTF16)ch; /* normal case */
+ }
+ } else if (ch > UNI_MAX_LEGAL_UTF32) {
+ if (flags == strictConversion) {
+ result = sourceIllegal;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ /* target is a character in range 0xFFFF - 0x10FFFF. */
+ if (target + 1 >= targetEnd) {
+ --source; /* Back up source pointer! */
+ result = targetExhausted; break;
+ }
+ ch -= halfBase;
+ *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
+ *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
+ }
}
*sourceStart = source;
*targetStart = target;
@@ -165,48 +165,48 @@ ConversionResult ConvertUTF32toUTF16 (
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF16toUTF32 (
- const UTF16** sourceStart, const UTF16* sourceEnd,
- UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
+ const UTF16** sourceStart, const UTF16* sourceEnd,
+ UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF16* source = *sourceStart;
UTF32* target = *targetStart;
UTF32 ch, ch2;
while (source < sourceEnd) {
- const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
- ch = *source++;
- /* If we have a surrogate pair, convert to UTF32 first. */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
- /* If the 16 bits following the high surrogate are in the source buffer... */
- if (source < sourceEnd) {
- ch2 = *source;
- /* If it's a low surrogate, convert to UTF32. */
- if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
- ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
- + (ch2 - UNI_SUR_LOW_START) + halfBase;
- ++source;
- } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- } else { /* We don't have the 16 bits following the high surrogate. */
- --source; /* return to the high surrogate */
- result = sourceExhausted;
- break;
- }
- } else if (flags == strictConversion) {
- /* UTF-16 surrogate values are illegal in UTF-32 */
- if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- }
- if (target >= targetEnd) {
- source = oldSource; /* Back up source pointer! */
- result = targetExhausted; break;
- }
- *target++ = ch;
+ const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
+ ch = *source++;
+ /* If we have a surrogate pair, convert to UTF32 first. */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
+ /* If the 16 bits following the high surrogate are in the source buffer... */
+ if (source < sourceEnd) {
+ ch2 = *source;
+ /* If it's a low surrogate, convert to UTF32. */
+ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
+ ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ + (ch2 - UNI_SUR_LOW_START) + halfBase;
+ ++source;
+ } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ } else { /* We don't have the 16 bits following the high surrogate. */
+ --source; /* return to the high surrogate */
+ result = sourceExhausted;
+ break;
+ }
+ } else if (flags == strictConversion) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ if (target >= targetEnd) {
+ source = oldSource; /* Back up source pointer! */
+ result = targetExhausted; break;
+ }
+ *target++ = ch;
}
*sourceStart = source;
*targetStart = target;
@@ -219,67 +219,67 @@ if (result == sourceIllegal) {
return result;
}
ConversionResult ConvertUTF16toUTF8 (
- const UTF16** sourceStart, const UTF16* sourceEnd,
- UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
+ const UTF16** sourceStart, const UTF16* sourceEnd,
+ UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF16* source = *sourceStart;
UTF8* target = *targetStart;
while (source < sourceEnd) {
- UTF32 ch;
- unsigned short bytesToWrite = 0;
- const UTF32 byteMask = 0xBF;
- const UTF32 byteMark = 0x80;
- const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
- ch = *source++;
- /* If we have a surrogate pair, convert to UTF32 first. */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
- /* If the 16 bits following the high surrogate are in the source buffer... */
- if (source < sourceEnd) {
- UTF32 ch2 = *source;
- /* If it's a low surrogate, convert to UTF32. */
- if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
- ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
- + (ch2 - UNI_SUR_LOW_START) + halfBase;
- ++source;
- } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- } else { /* We don't have the 16 bits following the high surrogate. */
- --source; /* return to the high surrogate */
- result = sourceExhausted;
- break;
- }
- } else if (flags == strictConversion) {
- /* UTF-16 surrogate values are illegal in UTF-32 */
- if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- }
- /* Figure out how many bytes the result will require */
- if (ch < (UTF32)0x80) { bytesToWrite = 1;
- } else if (ch < (UTF32)0x800) { bytesToWrite = 2;
- } else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
- } else if (ch < (UTF32)0x110000) { bytesToWrite = 4;
- } else { bytesToWrite = 3;
- ch = UNI_REPLACEMENT_CHAR;
- }
-
- target += bytesToWrite;
- if (target > targetEnd) {
- source = oldSource; /* Back up source pointer! */
- target -= bytesToWrite; result = targetExhausted; break;
- }
- switch (bytesToWrite) { /* note: everything falls through. */
- case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
- }
- target += bytesToWrite;
+ UTF32 ch;
+ unsigned short bytesToWrite = 0;
+ const UTF32 byteMask = 0xBF;
+ const UTF32 byteMark = 0x80;
+ const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
+ ch = *source++;
+ /* If we have a surrogate pair, convert to UTF32 first. */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
+ /* If the 16 bits following the high surrogate are in the source buffer... */
+ if (source < sourceEnd) {
+ UTF32 ch2 = *source;
+ /* If it's a low surrogate, convert to UTF32. */
+ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
+ ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ + (ch2 - UNI_SUR_LOW_START) + halfBase;
+ ++source;
+ } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ } else { /* We don't have the 16 bits following the high surrogate. */
+ --source; /* return to the high surrogate */
+ result = sourceExhausted;
+ break;
+ }
+ } else if (flags == strictConversion) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ /* Figure out how many bytes the result will require */
+ if (ch < (UTF32)0x80) { bytesToWrite = 1;
+ } else if (ch < (UTF32)0x800) { bytesToWrite = 2;
+ } else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
+ } else if (ch < (UTF32)0x110000) { bytesToWrite = 4;
+ } else { bytesToWrite = 3;
+ ch = UNI_REPLACEMENT_CHAR;
+ }
+
+ target += bytesToWrite;
+ if (target > targetEnd) {
+ source = oldSource; /* Back up source pointer! */
+ target -= bytesToWrite; result = targetExhausted; break;
+ }
+ switch (bytesToWrite) { /* note: everything falls through. */
+ case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
+ }
+ target += bytesToWrite;
}
*sourceStart = source;
*targetStart = target;
@@ -289,50 +289,50 @@ ConversionResult ConvertUTF16toUTF8 (
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF32toUTF8 (
- const UTF32** sourceStart, const UTF32* sourceEnd,
- UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
+ const UTF32** sourceStart, const UTF32* sourceEnd,
+ UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF32* source = *sourceStart;
UTF8* target = *targetStart;
while (source < sourceEnd) {
- UTF32 ch;
- unsigned short bytesToWrite = 0;
- const UTF32 byteMask = 0xBF;
- const UTF32 byteMark = 0x80;
- ch = *source++;
- if (flags == strictConversion ) {
- /* UTF-16 surrogate values are illegal in UTF-32 */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- }
- /*
- * Figure out how many bytes the result will require. Turn any
- * illegally large UTF32 things (> Plane 17) into replacement chars.
- */
- if (ch < (UTF32)0x80) { bytesToWrite = 1;
- } else if (ch < (UTF32)0x800) { bytesToWrite = 2;
- } else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
- } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4;
- } else { bytesToWrite = 3;
- ch = UNI_REPLACEMENT_CHAR;
- result = sourceIllegal;
- }
-
- target += bytesToWrite;
- if (target > targetEnd) {
- --source; /* Back up source pointer! */
- target -= bytesToWrite; result = targetExhausted; break;
- }
- switch (bytesToWrite) { /* note: everything falls through. */
- case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
- }
- target += bytesToWrite;
+ UTF32 ch;
+ unsigned short bytesToWrite = 0;
+ const UTF32 byteMask = 0xBF;
+ const UTF32 byteMark = 0x80;
+ ch = *source++;
+ if (flags == strictConversion ) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ /*
+ * Figure out how many bytes the result will require. Turn any
+ * illegally large UTF32 things (> Plane 17) into replacement chars.
+ */
+ if (ch < (UTF32)0x80) { bytesToWrite = 1;
+ } else if (ch < (UTF32)0x800) { bytesToWrite = 2;
+ } else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
+ } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4;
+ } else { bytesToWrite = 3;
+ ch = UNI_REPLACEMENT_CHAR;
+ result = sourceIllegal;
+ }
+
+ target += bytesToWrite;
+ if (target > targetEnd) {
+ --source; /* Back up source pointer! */
+ target -= bytesToWrite; result = targetExhausted; break;
+ }
+ switch (bytesToWrite) { /* note: everything falls through. */
+ case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
+ }
+ target += bytesToWrite;
}
*sourceStart = source;
*targetStart = target;
@@ -342,59 +342,59 @@ ConversionResult ConvertUTF32toUTF8 (
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF8toUTF32 (
- const UTF8** sourceStart, const UTF8* sourceEnd,
- UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
+ const UTF8** sourceStart, const UTF8* sourceEnd,
+ UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF8* source = *sourceStart;
UTF32* target = *targetStart;
while (source < sourceEnd) {
- UTF32 ch = 0;
- unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
- if (source + extraBytesToRead >= sourceEnd) {
- result = sourceExhausted; break;
- }
- /* Do this check whether lenient or strict */
- if (!isLegalUTF8(source, extraBytesToRead+1)) {
- result = sourceIllegal;
- break;
- }
- /*
- * The cases all fall through. See "Note A" below.
- */
- switch (extraBytesToRead) {
- case 5: ch += *source++; ch <<= 6;
- case 4: ch += *source++; ch <<= 6;
- case 3: ch += *source++; ch <<= 6;
- case 2: ch += *source++; ch <<= 6;
- case 1: ch += *source++; ch <<= 6;
- case 0: ch += *source++;
- }
- ch -= offsetsFromUTF8[extraBytesToRead];
-
- if (target >= targetEnd) {
- source -= (extraBytesToRead+1); /* Back up the source pointer! */
- result = targetExhausted; break;
- }
- if (ch <= UNI_MAX_LEGAL_UTF32) {
- /*
- * UTF-16 surrogate values are illegal in UTF-32, and anything
- * over Plane 17 (> 0x10FFFF) is illegal.
- */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
- if (flags == strictConversion) {
- source -= (extraBytesToRead+1); /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- *target++ = ch;
- }
- } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
- result = sourceIllegal;
- *target++ = UNI_REPLACEMENT_CHAR;
- }
+ UTF32 ch = 0;
+ unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
+ if (source + extraBytesToRead >= sourceEnd) {
+ result = sourceExhausted; break;
+ }
+ /* Do this check whether lenient or strict */
+ if (!isLegalUTF8(source, extraBytesToRead+1)) {
+ result = sourceIllegal;
+ break;
+ }
+ /*
+ * The cases all fall through. See "Note A" below.
+ */
+ switch (extraBytesToRead) {
+ case 5: ch += *source++; ch <<= 6;
+ case 4: ch += *source++; ch <<= 6;
+ case 3: ch += *source++; ch <<= 6;
+ case 2: ch += *source++; ch <<= 6;
+ case 1: ch += *source++; ch <<= 6;
+ case 0: ch += *source++;
+ }
+ ch -= offsetsFromUTF8[extraBytesToRead];
+
+ if (target >= targetEnd) {
+ source -= (extraBytesToRead+1); /* Back up the source pointer! */
+ result = targetExhausted; break;
+ }
+ if (ch <= UNI_MAX_LEGAL_UTF32) {
+ /*
+ * UTF-16 surrogate values are illegal in UTF-32, and anything
+ * over Plane 17 (> 0x10FFFF) is illegal.
+ */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ if (flags == strictConversion) {
+ source -= (extraBytesToRead+1); /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ *target++ = ch;
+ }
+ } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
+ result = sourceIllegal;
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
}
*sourceStart = source;
*targetStart = target;
@@ -420,19 +420,19 @@ static Boolean isLegalUTF8(const UTF8 *source, int length) {
const UTF8 *srcptr = source+length;
switch (length) {
default: return false;
- /* Everything else falls through when "true"... */
+ /* Everything else falls through when "true"... */
case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
case 2: if ((a = (*--srcptr)) > 0xBF) return false;
- switch (*source) {
- /* no fall-through in this inner switch */
- case 0xE0: if (a < 0xA0) return false; break;
- case 0xED: if (a > 0x9F) return false; break;
- case 0xF0: if (a < 0x90) return false; break;
- case 0xF4: if (a > 0x8F) return false; break;
- default: if (a < 0x80) return false;
- }
+ switch (*source) {
+ /* no fall-through in this inner switch */
+ case 0xE0: if (a < 0xA0) return false; break;
+ case 0xED: if (a > 0x9F) return false; break;
+ case 0xF0: if (a < 0x90) return false; break;
+ case 0xF4: if (a > 0x8F) return false; break;
+ default: if (a < 0x80) return false;
+ }
case 1: if (*source >= 0x80 && *source < 0xC2) return false;
}
@@ -449,7 +449,7 @@ static Boolean isLegalUTF8(const UTF8 *source, int length) {
Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
int length = trailingBytesForUTF8[*source]+1;
if (source+length > sourceEnd) {
- return false;
+ return false;
}
return isLegalUTF8(source, length);
}
@@ -457,70 +457,70 @@ Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF8toUTF16 (
- const UTF8** sourceStart, const UTF8* sourceEnd,
- UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
+ const UTF8** sourceStart, const UTF8* sourceEnd,
+ UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF8* source = *sourceStart;
UTF16* target = *targetStart;
while (source < sourceEnd) {
- UTF32 ch = 0;
- unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
- if (source + extraBytesToRead >= sourceEnd) {
- result = sourceExhausted; break;
- }
- /* Do this check whether lenient or strict */
- if (!isLegalUTF8(source, extraBytesToRead+1)) {
- result = sourceIllegal;
- break;
- }
- /*
- * The cases all fall through. See "Note A" below.
- */
- switch (extraBytesToRead) {
- case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
- case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
- case 3: ch += *source++; ch <<= 6;
- case 2: ch += *source++; ch <<= 6;
- case 1: ch += *source++; ch <<= 6;
- case 0: ch += *source++;
- }
- ch -= offsetsFromUTF8[extraBytesToRead];
-
- if (target >= targetEnd) {
- source -= (extraBytesToRead+1); /* Back up source pointer! */
- result = targetExhausted; break;
- }
- if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
- /* UTF-16 surrogate values are illegal in UTF-32 */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
- if (flags == strictConversion) {
- source -= (extraBytesToRead+1); /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- *target++ = (UTF16)ch; /* normal case */
- }
- } else if (ch > UNI_MAX_UTF16) {
- if (flags == strictConversion) {
- result = sourceIllegal;
- source -= (extraBytesToRead+1); /* return to the start */
- break; /* Bail out; shouldn't continue */
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- /* target is a character in range 0xFFFF - 0x10FFFF. */
- if (target + 1 >= targetEnd) {
- source -= (extraBytesToRead+1); /* Back up source pointer! */
- result = targetExhausted; break;
- }
- ch -= halfBase;
- *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
- *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
- }
+ UTF32 ch = 0;
+ unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
+ if (source + extraBytesToRead >= sourceEnd) {
+ result = sourceExhausted; break;
+ }
+ /* Do this check whether lenient or strict */
+ if (!isLegalUTF8(source, extraBytesToRead+1)) {
+ result = sourceIllegal;
+ break;
+ }
+ /*
+ * The cases all fall through. See "Note A" below.
+ */
+ switch (extraBytesToRead) {
+ case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
+ case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
+ case 3: ch += *source++; ch <<= 6;
+ case 2: ch += *source++; ch <<= 6;
+ case 1: ch += *source++; ch <<= 6;
+ case 0: ch += *source++;
+ }
+ ch -= offsetsFromUTF8[extraBytesToRead];
+
+ if (target >= targetEnd) {
+ source -= (extraBytesToRead+1); /* Back up source pointer! */
+ result = targetExhausted; break;
+ }
+ if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ if (flags == strictConversion) {
+ source -= (extraBytesToRead+1); /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ *target++ = (UTF16)ch; /* normal case */
+ }
+ } else if (ch > UNI_MAX_UTF16) {
+ if (flags == strictConversion) {
+ result = sourceIllegal;
+ source -= (extraBytesToRead+1); /* return to the start */
+ break; /* Bail out; shouldn't continue */
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ /* target is a character in range 0xFFFF - 0x10FFFF. */
+ if (target + 1 >= targetEnd) {
+ source -= (extraBytesToRead+1); /* Back up source pointer! */
+ result = targetExhausted; break;
+ }
+ ch -= halfBase;
+ *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
+ *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
+ }
}
*sourceStart = source;
*targetStart = target;
@@ -533,14 +533,14 @@ ConversionResult ConvertUTF8toUTF16 (
The fall-through switches in UTF-8 reading code save a
temp variable, some decrements & conditionals. The switches
are equivalent to the following loop:
- {
- int tmpBytesToRead = extraBytesToRead+1;
- do {
- ch += *source++;
- --tmpBytesToRead;
- if (tmpBytesToRead) ch <<= 6;
- } while (tmpBytesToRead > 0);
- }
+ {
+ int tmpBytesToRead = extraBytesToRead+1;
+ do {
+ ch += *source++;
+ --tmpBytesToRead;
+ if (tmpBytesToRead) ch <<= 6;
+ } while (tmpBytesToRead > 0);
+ }
In UTF-8 writing code, the switches on "bytesToWrite" are
similarly unrolled loops.
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index 78b8b0a855977..4a29997a2ccc3 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -49,7 +49,7 @@ struct StaticDiagInfoRec {
bool SFINAE : 1;
const char *Description;
const char *OptionGroup;
-
+
bool operator<(const StaticDiagInfoRec &RHS) const {
return DiagID < RHS.DiagID;
}
@@ -88,16 +88,16 @@ static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
IsFirst = false;
}
#endif
-
+
// Search the diagnostic table with a binary search.
StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0, 0 };
-
+
const StaticDiagInfoRec *Found =
std::lower_bound(StaticDiagInfo, StaticDiagInfo + NumDiagEntries, Find);
if (Found == StaticDiagInfo + NumDiagEntries ||
Found->DiagID != DiagID)
return 0;
-
+
return Found;
}
@@ -141,7 +141,7 @@ namespace clang {
std::vector<DiagDesc> DiagInfo;
std::map<DiagDesc, unsigned> DiagIDs;
public:
-
+
/// getDescription - Return the description of the specified custom
/// diagnostic.
const char *getDescription(unsigned DiagID) const {
@@ -149,14 +149,14 @@ namespace clang {
"Invalid diagnosic ID");
return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second.c_str();
}
-
+
/// getLevel - Return the level of the specified custom diagnostic.
Diagnostic::Level getLevel(unsigned DiagID) const {
assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
"Invalid diagnosic ID");
return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
}
-
+
unsigned getOrCreateDiagID(Diagnostic::Level L, const char *Message,
Diagnostic &Diags) {
DiagDesc D(L, Message);
@@ -164,7 +164,7 @@ namespace clang {
std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
if (I != DiagIDs.end() && I->first == D)
return I->second;
-
+
// If not, assign a new ID.
unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
DiagIDs.insert(std::make_pair(D, ID));
@@ -172,9 +172,9 @@ namespace clang {
return ID;
}
};
-
- } // end diag namespace
-} // end clang namespace
+
+ } // end diag namespace
+} // end clang namespace
//===----------------------------------------------------------------------===//
@@ -196,32 +196,48 @@ Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) {
IgnoreAllWarnings = false;
WarningsAsErrors = false;
SuppressSystemWarnings = false;
+ SuppressAllDiagnostics = false;
ExtBehavior = Ext_Ignore;
-
+
ErrorOccurred = false;
FatalErrorOccurred = false;
NumDiagnostics = 0;
+
NumErrors = 0;
CustomDiagInfo = 0;
CurDiagID = ~0U;
LastDiagLevel = Ignored;
-
+
ArgToStringFn = DummyArgToStringFn;
ArgToStringCookie = 0;
-
+
// Set all mappings to 'unset'.
- memset(DiagMappings, 0, sizeof(DiagMappings));
+ DiagMappings BlankDiags(diag::DIAG_UPPER_LIMIT/2, 0);
+ DiagMappingsStack.push_back(BlankDiags);
}
Diagnostic::~Diagnostic() {
delete CustomDiagInfo;
}
+
+void Diagnostic::pushMappings() {
+ DiagMappingsStack.push_back(DiagMappingsStack.back());
+}
+
+bool Diagnostic::popMappings() {
+ if (DiagMappingsStack.size() == 1)
+ return false;
+
+ DiagMappingsStack.pop_back();
+ return true;
+}
+
/// getCustomDiagID - Return an ID for a diagnostic with the specified message
/// and level. If this is the first request for this diagnosic, it is
/// registered and created, otherwise the existing ID is returned.
unsigned Diagnostic::getCustomDiagID(Level L, const char *Message) {
- if (CustomDiagInfo == 0)
+ if (CustomDiagInfo == 0)
CustomDiagInfo = new diag::CustomDiagInfo();
return CustomDiagInfo->getOrCreateDiagID(L, Message, *this);
}
@@ -267,7 +283,7 @@ Diagnostic::Level Diagnostic::getDiagnosticLevel(unsigned DiagID) const {
// Handle custom diagnostics, which cannot be mapped.
if (DiagID >= diag::DIAG_UPPER_LIMIT)
return CustomDiagInfo->getLevel(DiagID);
-
+
unsigned DiagClass = getBuiltinDiagClass(DiagID);
assert(DiagClass != CLASS_NOTE && "Cannot get diagnostic level of a note!");
return getDiagnosticLevel(DiagID, DiagClass);
@@ -281,14 +297,14 @@ Diagnostic::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const {
// Specific non-error diagnostics may be mapped to various levels from ignored
// to error. Errors can only be mapped to fatal.
Diagnostic::Level Result = Diagnostic::Fatal;
-
+
// Get the mapping information, if unset, compute it lazily.
unsigned MappingInfo = getDiagnosticMappingInfo((diag::kind)DiagID);
if (MappingInfo == 0) {
MappingInfo = GetDefaultDiagMapping(DiagID);
setDiagnosticMappingInternal(DiagID, MappingInfo, false);
}
-
+
switch (MappingInfo & 7) {
default: assert(0 && "Unknown mapping!");
case diag::MAP_IGNORE:
@@ -311,29 +327,29 @@ Diagnostic::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const {
// If warnings are globally mapped to ignore or error, do it.
if (IgnoreAllWarnings)
return Diagnostic::Ignored;
-
+
Result = Diagnostic::Warning;
-
+
// If this is an extension diagnostic and we're in -pedantic-error mode, and
// if the user didn't explicitly map it, upgrade to an error.
if (ExtBehavior == Ext_Error &&
(MappingInfo & 8) == 0 &&
isBuiltinExtensionDiag(DiagID))
Result = Diagnostic::Error;
-
+
if (WarningsAsErrors)
Result = Diagnostic::Error;
break;
-
+
case diag::MAP_WARNING_NO_WERROR:
// Diagnostics specified with -Wno-error=foo should be set to warnings, but
// not be adjusted by -Werror or -pedantic-errors.
Result = Diagnostic::Warning;
-
+
// If warnings are globally mapped to ignore or error, do it.
if (IgnoreAllWarnings)
return Diagnostic::Ignored;
-
+
break;
}
@@ -342,7 +358,7 @@ Diagnostic::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const {
// block, silence it.
if (AllExtensionsSilenced && isBuiltinExtensionDiag(DiagID))
return Diagnostic::Ignored;
-
+
return Result;
}
@@ -377,7 +393,7 @@ static void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping,
for (; *Member != -1; ++Member)
Diags.setDiagnosticMapping(*Member, Mapping);
}
-
+
// Enable/disable all subgroups along with this one.
if (const char *SubGroups = Group->SubGroups) {
for (; *SubGroups != (char)-1; ++SubGroups)
@@ -390,7 +406,7 @@ static void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping,
/// ignores the request if "Group" was unknown, false otherwise.
bool Diagnostic::setDiagnosticGroupMapping(const char *Group,
diag::Mapping Map) {
-
+
WarningOption Key = { Group, 0, 0 };
const WarningOption *Found =
std::lower_bound(OptionTable, OptionTable + OptionTableSize, Key,
@@ -398,7 +414,7 @@ bool Diagnostic::setDiagnosticGroupMapping(const char *Group,
if (Found == OptionTable + OptionTableSize ||
strcmp(Found->Name, Group) != 0)
return true; // Option not found.
-
+
MapGroupMembers(Found, Map, *this);
return false;
}
@@ -408,19 +424,22 @@ bool Diagnostic::setDiagnosticGroupMapping(const char *Group,
/// finally fully formed.
bool Diagnostic::ProcessDiag() {
DiagnosticInfo Info(this);
-
+
+ if (SuppressAllDiagnostics)
+ return false;
+
// Figure out the diagnostic level of this message.
Diagnostic::Level DiagLevel;
unsigned DiagID = Info.getID();
-
+
// ShouldEmitInSystemHeader - True if this diagnostic should be produced even
// in a system header.
bool ShouldEmitInSystemHeader;
-
+
if (DiagID >= diag::DIAG_UPPER_LIMIT) {
// Handle custom diagnostics, which cannot be mapped.
DiagLevel = CustomDiagInfo->getLevel(DiagID);
-
+
// Custom diagnostics always are emitted in system headers.
ShouldEmitInSystemHeader = true;
} else {
@@ -432,12 +451,12 @@ bool Diagnostic::ProcessDiag() {
DiagLevel = Diagnostic::Note;
ShouldEmitInSystemHeader = false; // extra consideration is needed
} else {
- // If this is not an error and we are in a system header, we ignore it.
+ // If this is not an error and we are in a system header, we ignore it.
// Check the original Diag ID here, because we also want to ignore
// extensions and warnings in -Werror and -pedantic-errors modes, which
// *map* warnings/extensions to errors.
ShouldEmitInSystemHeader = DiagClass == CLASS_ERROR;
-
+
DiagLevel = getDiagnosticLevel(DiagID, DiagClass);
}
}
@@ -451,7 +470,7 @@ bool Diagnostic::ProcessDiag() {
FatalErrorOccurred = true;
LastDiagLevel = DiagLevel;
- }
+ }
// If a fatal error has already been emitted, silence all subsequent
// diagnostics.
@@ -478,7 +497,7 @@ bool Diagnostic::ProcessDiag() {
ErrorOccurred = true;
++NumErrors;
}
-
+
// Finally, report it.
Client->HandleDiagnostic(DiagLevel, Info);
if (Client->IncludeInDiagnosticCounts()) ++NumDiagnostics;
@@ -508,7 +527,7 @@ static void HandleSelectModifier(unsigned ValNo,
const char *Argument, unsigned ArgumentLen,
llvm::SmallVectorImpl<char> &OutStr) {
const char *ArgumentEnd = Argument+ArgumentLen;
-
+
// Skip over 'ValNo' |'s.
while (ValNo) {
const char *NextVal = std::find(Argument, ArgumentEnd, '|');
@@ -517,7 +536,7 @@ static void HandleSelectModifier(unsigned ValNo,
Argument = NextVal+1; // Skip this string.
--ValNo;
}
-
+
// Get the end of the value. This is either the } or the |.
const char *EndPtr = std::find(Argument, ArgumentEnd, '|');
// Add the value to the output string.
@@ -590,7 +609,7 @@ static bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End) {
// Scan for next or-expr part.
Start = std::find(Start, End, ',');
- if(Start == End)
+ if (Start == End)
break;
++Start;
}
@@ -659,7 +678,7 @@ void DiagnosticInfo::
FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
const char *DiagStr = getDiags()->getDescription(getID());
const char *DiagEnd = DiagStr+strlen(DiagStr);
-
+
while (DiagStr != DiagEnd) {
if (DiagStr[0] != '%') {
// Append non-%0 substrings to Str if we have one.
@@ -672,10 +691,10 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
DiagStr += 2;
continue;
}
-
+
// Skip the %.
++DiagStr;
-
+
// This must be a placeholder for a diagnostic argument. The format for a
// placeholder is one of "%0", "%modifier0", or "%modifier{arguments}0".
// The digit is a number from 0-9 indicating which argument this comes from.
@@ -683,7 +702,7 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
// brace enclosed string.
const char *Modifier = 0, *Argument = 0;
unsigned ModifierLen = 0, ArgumentLen = 0;
-
+
// Check to see if we have a modifier. If so eat it.
if (!isdigit(DiagStr[0])) {
Modifier = DiagStr;
@@ -696,14 +715,14 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
if (DiagStr[0] == '{') {
++DiagStr; // Skip {.
Argument = DiagStr;
-
+
for (; DiagStr[0] != '}'; ++DiagStr)
assert(DiagStr[0] && "Mismatched {}'s in diagnostic string!");
ArgumentLen = DiagStr-Argument;
++DiagStr; // Skip }.
}
}
-
+
assert(isdigit(*DiagStr) && "Invalid format for argument in diagnostic");
unsigned ArgNo = *DiagStr++ - '0';
@@ -722,14 +741,14 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
// Don't crash if get passed a null pointer by accident.
if (!S)
S = "(null)";
-
+
OutStr.append(S, S + strlen(S));
break;
}
// ---- INTEGERS ----
case Diagnostic::ak_sint: {
int Val = getArgSInt(ArgNo);
-
+
if (ModifierIs(Modifier, ModifierLen, "select")) {
HandleSelectModifier((unsigned)Val, Argument, ArgumentLen, OutStr);
} else if (ModifierIs(Modifier, ModifierLen, "s")) {
@@ -746,7 +765,7 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
}
case Diagnostic::ak_uint: {
unsigned Val = getArgUInt(ArgNo);
-
+
if (ModifierIs(Modifier, ModifierLen, "select")) {
HandleSelectModifier(Val, Argument, ArgumentLen, OutStr);
} else if (ModifierIs(Modifier, ModifierLen, "s")) {
@@ -755,7 +774,7 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
HandlePluralModifier((unsigned)Val, Argument, ArgumentLen, OutStr);
} else {
assert(ModifierLen == 0 && "Unknown integer modifier");
-
+
// FIXME: Optimize
std::string S = llvm::utostr_32(Val);
OutStr.append(S.begin(), S.end());
@@ -782,6 +801,8 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
case Diagnostic::ak_qualtype:
case Diagnostic::ak_declarationname:
case Diagnostic::ak_nameddecl:
+ case Diagnostic::ak_nestednamespec:
+ case Diagnostic::ak_declcontext:
getDiags()->ConvertArgToString(getArgKind(ArgNo), getRawArg(ArgNo),
Modifier, ModifierLen,
Argument, ArgumentLen, OutStr);
diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp
index cc25d33051586..df86f9d04702e 100644
--- a/lib/Basic/FileManager.cpp
+++ b/lib/Basic/FileManager.cpp
@@ -19,9 +19,12 @@
#include "clang/Basic/FileManager.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
-#include "llvm/Support/Streams.h"
#include "llvm/Config/config.h"
+#include <map>
+#include <set>
+#include <string>
using namespace clang;
// FIXME: Enhance libsystem to support inode and other fields.
@@ -44,8 +47,7 @@ using namespace clang;
#define IS_DIR_SEPARATOR_CHAR(x) ((x) == '/' || (x) == '\\')
namespace {
- static std::string GetFullPath(const char *relPath)
- {
+ static std::string GetFullPath(const char *relPath) {
char *absPathStrPtr = _fullpath(NULL, relPath, 0);
assert(absPathStrPtr && "_fullpath() returned NULL!");
@@ -59,7 +61,7 @@ namespace {
class FileManager::UniqueDirContainer {
/// UniqueDirs - Cache from full path to existing directories/files.
///
- llvm::StringMap<DirectoryEntry> UniqueDirs;
+ llvm::StringMap<DirectoryEntry> UniqueDirs;
public:
DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) {
@@ -69,7 +71,7 @@ public:
FullPath.c_str() + FullPath.size()
).getValue();
}
-
+
size_t size() { return UniqueDirs.size(); }
};
@@ -101,7 +103,7 @@ public:
class FileManager::UniqueDirContainer {
/// UniqueDirs - Cache from ID's to existing directories/files.
///
- std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs;
+ std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs;
public:
DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) {
@@ -149,27 +151,27 @@ FileManager::~FileManager() {
/// getDirectory - Lookup, cache, and verify the specified directory. This
/// returns null if the directory doesn't exist.
-///
+///
const DirectoryEntry *FileManager::getDirectory(const char *NameStart,
const char *NameEnd) {
++NumDirLookups;
llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt =
DirEntries.GetOrCreateValue(NameStart, NameEnd);
-
+
// See if there is already an entry in the map.
if (NamedDirEnt.getValue())
return NamedDirEnt.getValue() == NON_EXISTENT_DIR
? 0 : NamedDirEnt.getValue();
-
+
++NumDirCacheMisses;
-
+
// By default, initialize it to invalid.
NamedDirEnt.setValue(NON_EXISTENT_DIR);
-
+
// Get the null-terminated directory name as stored as the key of the
// DirEntries map.
const char *InterndDirName = NamedDirEnt.getKeyData();
-
+
// Check to see if the directory exists.
struct stat StatBuf;
if (stat_cached(InterndDirName, &StatBuf) || // Error stat'ing.
@@ -177,13 +179,13 @@ const DirectoryEntry *FileManager::getDirectory(const char *NameStart,
return 0;
// It exists. See if we have already opened a directory with the same inode.
- // This occurs when one dir is symlinked to another, for example.
+ // This occurs when one dir is symlinked to another, for example.
DirectoryEntry &UDE = UniqueDirs.getDirectory(InterndDirName, StatBuf);
-
+
NamedDirEnt.setValue(&UDE);
if (UDE.getName()) // Already have an entry with this inode, return it.
return &UDE;
-
+
// Otherwise, we don't have this directory yet, add it. We use the string
// key from the DirEntries map as the string.
UDE.Name = InterndDirName;
@@ -196,11 +198,11 @@ const DirectoryEntry *FileManager::getDirectory(const char *NameStart,
/// getFile - Lookup, cache, and verify the specified file. This returns null
/// if the file doesn't exist.
-///
+///
const FileEntry *FileManager::getFile(const char *NameStart,
const char *NameEnd) {
++NumFileLookups;
-
+
// See if there is already an entry in the map.
llvm::StringMapEntry<FileEntry *> &NamedFileEnt =
FileEntries.GetOrCreateValue(NameStart, NameEnd);
@@ -209,7 +211,7 @@ const FileEntry *FileManager::getFile(const char *NameStart,
if (NamedFileEnt.getValue())
return NamedFileEnt.getValue() == NON_EXISTENT_FILE
? 0 : NamedFileEnt.getValue();
-
+
++NumFileCacheMisses;
// By default, initialize it to invalid.
@@ -221,7 +223,10 @@ const FileEntry *FileManager::getFile(const char *NameStart,
const char *SlashPos = NameEnd-1;
while (SlashPos >= NameStart && !IS_DIR_SEPARATOR_CHAR(SlashPos[0]))
--SlashPos;
-
+ // Ignore duplicate //'s.
+ while (SlashPos > NameStart && IS_DIR_SEPARATOR_CHAR(SlashPos[-1]))
+ --SlashPos;
+
const DirectoryEntry *DirInfo;
if (SlashPos < NameStart) {
// Use the current directory if file has no path component.
@@ -231,32 +236,32 @@ const FileEntry *FileManager::getFile(const char *NameStart,
return 0; // If filename ends with a /, it's a directory.
else
DirInfo = getDirectory(NameStart, SlashPos);
-
+
if (DirInfo == 0) // Directory doesn't exist, file can't exist.
return 0;
-
+
// Get the null-terminated file name as stored as the key of the
// FileEntries map.
const char *InterndFileName = NamedFileEnt.getKeyData();
-
+
// FIXME: Use the directory info to prune this, before doing the stat syscall.
// FIXME: This will reduce the # syscalls.
-
+
// Nope, there isn't. Check to see if the file exists.
struct stat StatBuf;
- //llvm::cerr << "STATING: " << Filename;
+ //llvm::errs() << "STATING: " << Filename;
if (stat_cached(InterndFileName, &StatBuf) || // Error stat'ing.
S_ISDIR(StatBuf.st_mode)) { // A directory?
// If this file doesn't exist, we leave a null in FileEntries for this path.
- //llvm::cerr << ": Not existing\n";
+ //llvm::errs() << ": Not existing\n";
return 0;
}
- //llvm::cerr << ": exists\n";
-
+ //llvm::errs() << ": exists\n";
+
// It exists. See if we have already opened a file with the same inode.
// This occurs when one dir is symlinked to another, for example.
FileEntry &UFE = UniqueFiles.getFile(InterndFileName, StatBuf);
-
+
NamedFileEnt.setValue(&UFE);
if (UFE.getName()) // Already have an entry with this inode, return it.
return &UFE;
@@ -273,23 +278,24 @@ const FileEntry *FileManager::getFile(const char *NameStart,
}
void FileManager::PrintStats() const {
- llvm::cerr << "\n*** File Manager Stats:\n";
- llvm::cerr << UniqueFiles.size() << " files found, "
- << UniqueDirs.size() << " dirs found.\n";
- llvm::cerr << NumDirLookups << " dir lookups, "
- << NumDirCacheMisses << " dir cache misses.\n";
- llvm::cerr << NumFileLookups << " file lookups, "
- << NumFileCacheMisses << " file cache misses.\n";
-
- //llvm::cerr << PagesMapped << BytesOfPagesMapped << FSLookups;
+ llvm::errs() << "\n*** File Manager Stats:\n";
+ llvm::errs() << UniqueFiles.size() << " files found, "
+ << UniqueDirs.size() << " dirs found.\n";
+ llvm::errs() << NumDirLookups << " dir lookups, "
+ << NumDirCacheMisses << " dir cache misses.\n";
+ llvm::errs() << NumFileLookups << " file lookups, "
+ << NumFileCacheMisses << " file cache misses.\n";
+
+ //llvm::errs() << PagesMapped << BytesOfPagesMapped << FSLookups;
}
int MemorizeStatCalls::stat(const char *path, struct stat *buf) {
int result = ::stat(path, buf);
-
- if (result != 0) {
+
+ if (result != 0) {
// Cache failed 'stat' results.
struct stat empty;
+ memset(&empty, 0, sizeof(empty));
StatCalls[path] = StatResult(result, empty);
}
else if (!S_ISDIR(buf->st_mode) || llvm::sys::Path(path).isAbsolute()) {
@@ -297,6 +303,6 @@ int MemorizeStatCalls::stat(const char *path, struct stat *buf) {
// paths.
StatCalls[path] = StatResult(result, *buf);
}
-
- return result;
+
+ return result;
}
diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp
index 3810c49f71f31..93c260fdbe17a 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/lib/Basic/IdentifierTable.cpp
@@ -109,9 +109,9 @@ static void AddCXXOperatorKeyword(const char *Keyword, unsigned KWLen,
Info.setIsCPlusPlusOperatorKeyword();
}
-/// AddObjCKeyword - Register an Objective-C @keyword like "class" "selector" or
+/// AddObjCKeyword - Register an Objective-C @keyword like "class" "selector" or
/// "property".
-static void AddObjCKeyword(tok::ObjCKeywordKind ObjCID,
+static void AddObjCKeyword(tok::ObjCKeywordKind ObjCID,
const char *Name, unsigned NameLen,
IdentifierTable &Table) {
Table.get(Name, Name+NameLen).setObjCKeywordID(ObjCID);
@@ -144,13 +144,13 @@ tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
// the first and third character. For preprocessor ID's there are no
// collisions (if there were, the switch below would complain about duplicate
// case values). Note that this depends on 'if' being null terminated.
-
+
#define HASH(LEN, FIRST, THIRD) \
(LEN << 5) + (((FIRST-'a') + (THIRD-'a')) & 31)
#define CASE(LEN, FIRST, THIRD, NAME) \
case HASH(LEN, FIRST, THIRD): \
return memcmp(Name, #NAME, LEN) ? tok::pp_not_keyword : tok::pp_ ## NAME
-
+
unsigned Len = getLength();
if (Len < 2) return tok::pp_not_keyword;
const char *Name = getName();
@@ -179,7 +179,7 @@ tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
CASE( 8, 'u', 'a', unassert);
CASE(12, 'i', 'c', include_next);
-
+
CASE(16, '_', 'i', __include_macros);
#undef CASE
#undef HASH
@@ -198,7 +198,7 @@ void IdentifierTable::PrintStats() const {
unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
unsigned AverageIdentifierSize = 0;
unsigned MaxIdentifierLength = 0;
-
+
// TODO: Figure out maximum times an identifier had to probe for -stats.
for (llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator>::const_iterator
I = HashTable.begin(), E = HashTable.end(); I != E; ++I) {
@@ -207,7 +207,7 @@ void IdentifierTable::PrintStats() const {
if (MaxIdentifierLength < IdLen)
MaxIdentifierLength = IdLen;
}
-
+
fprintf(stderr, "\n*** Identifier Table Stats:\n");
fprintf(stderr, "# Identifiers: %d\n", NumIdentifiers);
fprintf(stderr, "# Empty Buckets: %d\n", NumEmptyBuckets);
@@ -216,7 +216,7 @@ void IdentifierTable::PrintStats() const {
fprintf(stderr, "Ave identifier length: %f\n",
(AverageIdentifierSize/(double)NumIdentifiers));
fprintf(stderr, "Max identifier length: %d\n", MaxIdentifierLength);
-
+
// Compute statistics about the memory allocated for identifiers.
HashTable.getAllocator().PrintStats();
}
@@ -232,42 +232,42 @@ unsigned llvm::DenseMapInfo<clang::Selector>::getHashValue(clang::Selector S) {
namespace clang {
/// MultiKeywordSelector - One of these variable length records is kept for each
/// selector containing more than one keyword. We use a folding set
-/// to unique aggregate names (keyword selectors in ObjC parlance). Access to
+/// to unique aggregate names (keyword selectors in ObjC parlance). Access to
/// this class is provided strictly through Selector.
-class MultiKeywordSelector
+class MultiKeywordSelector
: public DeclarationNameExtra, public llvm::FoldingSetNode {
MultiKeywordSelector(unsigned nKeys) {
ExtraKindOrNumArgs = NUM_EXTRA_KINDS + nKeys;
}
-public:
+public:
// Constructor for keyword selectors.
MultiKeywordSelector(unsigned nKeys, IdentifierInfo **IIV) {
assert((nKeys > 1) && "not a multi-keyword selector");
ExtraKindOrNumArgs = NUM_EXTRA_KINDS + nKeys;
-
+
// Fill in the trailing keyword array.
IdentifierInfo **KeyInfo = reinterpret_cast<IdentifierInfo **>(this+1);
for (unsigned i = 0; i != nKeys; ++i)
KeyInfo[i] = IIV[i];
- }
-
+ }
+
// getName - Derive the full selector name and return it.
std::string getName() const;
-
+
unsigned getNumArgs() const { return ExtraKindOrNumArgs - NUM_EXTRA_KINDS; }
-
+
typedef IdentifierInfo *const *keyword_iterator;
keyword_iterator keyword_begin() const {
return reinterpret_cast<keyword_iterator>(this+1);
}
- keyword_iterator keyword_end() const {
- return keyword_begin()+getNumArgs();
+ keyword_iterator keyword_end() const {
+ return keyword_begin()+getNumArgs();
}
IdentifierInfo *getIdentifierInfoForSlot(unsigned i) const {
assert(i < getNumArgs() && "getIdentifierInfoForSlot(): illegal index");
return keyword_begin()[i];
}
- static void Profile(llvm::FoldingSetNodeID &ID,
+ static void Profile(llvm::FoldingSetNodeID &ID,
keyword_iterator ArgTys, unsigned NumArgs) {
ID.AddInteger(NumArgs);
for (unsigned i = 0; i != NumArgs; ++i)
@@ -287,7 +287,7 @@ unsigned Selector::getNumArgs() const {
return 1;
// We point to a MultiKeywordSelector (pointer doesn't contain any flags).
MultiKeywordSelector *SI = reinterpret_cast<MultiKeywordSelector *>(InfoPtr);
- return SI->getNumArgs();
+ return SI->getNumArgs();
}
IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) const {
@@ -308,16 +308,16 @@ std::string MultiKeywordSelector::getName() const {
Length += (*I)->getLength();
++Length; // :
}
-
+
Result.reserve(Length);
-
+
for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
if (*I)
Result.insert(Result.end(), (*I)->getName(),
(*I)->getName()+(*I)->getLength());
Result.push_back(':');
}
-
+
return Result;
}
@@ -327,7 +327,7 @@ std::string Selector::getAsString() const {
if (InfoPtr & ArgFlags) {
IdentifierInfo *II = getAsIdentifierInfo();
-
+
// If the number of arguments is 0 then II is guaranteed to not be null.
if (getNumArgs() == 0)
return II->getName();
@@ -336,7 +336,7 @@ std::string Selector::getAsString() const {
Res += ":";
return Res;
}
-
+
// We have a multiple keyword selector (no embedded flags).
return reinterpret_cast<MultiKeywordSelector *>(InfoPtr)->getName();
}
@@ -357,9 +357,9 @@ static SelectorTableImpl &getSelectorTableImpl(void *P) {
Selector SelectorTable::getSelector(unsigned nKeys, IdentifierInfo **IIV) {
if (nKeys < 2)
return Selector(IIV[0], nKeys);
-
+
SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl);
-
+
// Unique selector, to guarantee there is one per name.
llvm::FoldingSetNodeID ID;
MultiKeywordSelector::Profile(ID, IIV, nKeys);
@@ -368,12 +368,12 @@ Selector SelectorTable::getSelector(unsigned nKeys, IdentifierInfo **IIV) {
if (MultiKeywordSelector *SI =
SelTabImpl.Table.FindNodeOrInsertPos(ID, InsertPos))
return Selector(SI);
-
+
// MultiKeywordSelector objects are not allocated with new because they have a
// variable size array (for parameter types) at the end of them.
unsigned Size = sizeof(MultiKeywordSelector) + nKeys*sizeof(IdentifierInfo *);
MultiKeywordSelector *SI =
- (MultiKeywordSelector*)SelTabImpl.Allocator.Allocate(Size,
+ (MultiKeywordSelector*)SelTabImpl.Allocator.Allocate(Size,
llvm::alignof<MultiKeywordSelector>());
new (SI) MultiKeywordSelector(nKeys, IIV);
SelTabImpl.Table.InsertNode(SI, InsertPos);
diff --git a/lib/Basic/Makefile b/lib/Basic/Makefile
index 3fd6c2c153842..5bd4314f45cdc 100644
--- a/lib/Basic/Makefile
+++ b/lib/Basic/Makefile
@@ -20,3 +20,14 @@ CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
include $(LEVEL)/Makefile.common
+SVN_REVISION := $(shell cd $(PROJ_SRC_DIR)/../.. && svnversion)
+
+CPP.Defines += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include \
+ -DSVN_REVISION='"$(SVN_REVISION)"'
+
+$(ObjDir)/.ver-svn .ver: $(ObjDir)/.dir
+ @if [ '$(SVN_REVISION)' != '$(shell cat $(ObjDir)/.ver-svn 2>/dev/null)' ]; then\
+ echo '$(SVN_REVISION)' > $(ObjDir)/.ver-svn; \
+ fi
+$(ObjDir)/.ver-svn: .ver
+$(ObjDir)/Version.o: $(ObjDir)/.ver-svn
diff --git a/lib/Basic/SourceLocation.cpp b/lib/Basic/SourceLocation.cpp
index f21ec8b1e9d7e..578a4eb34bab5 100644
--- a/lib/Basic/SourceLocation.cpp
+++ b/lib/Basic/SourceLocation.cpp
@@ -40,7 +40,7 @@ void SourceLocation::print(llvm::raw_ostream &OS, const SourceManager &SM)const{
OS << "<invalid loc>";
return;
}
-
+
if (isFileID()) {
PresumedLoc PLoc = SM.getPresumedLoc(*this);
// The instantiation and spelling pos is identical for file locs.
@@ -48,7 +48,7 @@ void SourceLocation::print(llvm::raw_ostream &OS, const SourceManager &SM)const{
<< ':' << PLoc.getColumn();
return;
}
-
+
SM.getInstantiationLoc(*this).print(OS, SM);
OS << " <Spelling=";
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index 6640c61ff3b79..962cb4c42a8ab 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -16,10 +16,9 @@
#include "clang/Basic/FileManager.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
-#include "llvm/Support/Streams.h"
#include <algorithm>
-#include <iostream>
using namespace clang;
using namespace SrcMgr;
using llvm::MemoryBuffer;
@@ -42,29 +41,74 @@ unsigned ContentCache::getSizeBytesMapped() const {
/// getSize - Returns the size of the content encapsulated by this ContentCache.
/// This can be the size of the source file or the size of an arbitrary
/// scratch buffer. If the ContentCache encapsulates a source file, that
-/// file is not lazily brought in from disk to satisfy this query.
+/// file is not lazily brought in from disk to satisfy this query unless it
+/// needs to be truncated due to a truncateAt() call.
unsigned ContentCache::getSize() const {
- return Entry ? Entry->getSize() : Buffer->getBufferSize();
+ return Buffer ? Buffer->getBufferSize() : Entry->getSize();
}
-const llvm::MemoryBuffer *ContentCache::getBuffer() const {
+const llvm::MemoryBuffer *ContentCache::getBuffer() const {
// Lazily create the Buffer for ContentCaches that wrap files.
if (!Buffer && Entry) {
// FIXME: Should we support a way to not have to do this check over
// and over if we cannot open the file?
Buffer = MemoryBuffer::getFile(Entry->getName(), 0, Entry->getSize());
+ if (isTruncated())
+ const_cast<ContentCache *>(this)->truncateAt(TruncateAtLine,
+ TruncateAtColumn);
}
return Buffer;
}
+void ContentCache::truncateAt(unsigned Line, unsigned Column) {
+ TruncateAtLine = Line;
+ TruncateAtColumn = Column;
+
+ if (!isTruncated() || !Buffer)
+ return;
+
+ // Find the byte position of the truncation point.
+ const char *Position = Buffer->getBufferStart();
+ for (unsigned Line = 1; Line < TruncateAtLine; ++Line) {
+ for (; *Position; ++Position) {
+ if (*Position != '\r' && *Position != '\n')
+ continue;
+
+ // Eat \r\n or \n\r as a single line.
+ if ((Position[1] == '\r' || Position[1] == '\n') &&
+ Position[0] != Position[1])
+ ++Position;
+ ++Position;
+ break;
+ }
+ }
+
+ for (unsigned Column = 1; Column < TruncateAtColumn; ++Column, ++Position) {
+ if (!*Position)
+ break;
+
+ if (*Position == '\t')
+ Column += 7;
+ }
+
+ // Truncate the buffer.
+ if (Position != Buffer->getBufferEnd()) {
+ MemoryBuffer *TruncatedBuffer
+ = MemoryBuffer::getMemBufferCopy(Buffer->getBufferStart(), Position,
+ Buffer->getBufferIdentifier());
+ delete Buffer;
+ Buffer = TruncatedBuffer;
+ }
+}
+
unsigned LineTableInfo::getLineTableFilenameID(const char *Ptr, unsigned Len) {
// Look up the filename in the string table, returning the pre-existing value
// if it exists.
- llvm::StringMapEntry<unsigned> &Entry =
+ llvm::StringMapEntry<unsigned> &Entry =
FilenameIDs.GetOrCreateValue(Ptr, Ptr+Len, ~0U);
if (Entry.getValue() != ~0U)
return Entry.getValue();
-
+
// Otherwise, assign this the next available ID.
Entry.setValue(FilenamesByID.size());
FilenamesByID.push_back(&Entry);
@@ -77,25 +121,25 @@ unsigned LineTableInfo::getLineTableFilenameID(const char *Ptr, unsigned Len) {
void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset,
unsigned LineNo, int FilenameID) {
std::vector<LineEntry> &Entries = LineEntries[FID];
-
+
assert((Entries.empty() || Entries.back().FileOffset < Offset) &&
"Adding line entries out of order!");
-
+
SrcMgr::CharacteristicKind Kind = SrcMgr::C_User;
unsigned IncludeOffset = 0;
-
+
if (!Entries.empty()) {
// If this is a '#line 4' after '#line 42 "foo.h"', make sure to remember
// that we are still in "foo.h".
if (FilenameID == -1)
FilenameID = Entries.back().FilenameID;
-
+
// If we are after a line marker that switched us to system header mode, or
// that set #include information, preserve it.
Kind = Entries.back().FileKind;
IncludeOffset = Entries.back().IncludeOffset;
}
-
+
Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID, Kind,
IncludeOffset));
}
@@ -110,9 +154,9 @@ void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset,
unsigned EntryExit,
SrcMgr::CharacteristicKind FileKind) {
assert(FilenameID != -1 && "Unspecified filename should use other accessor");
-
+
std::vector<LineEntry> &Entries = LineEntries[FID];
-
+
assert((Entries.empty() || Entries.back().FileOffset < Offset) &&
"Adding line entries out of order!");
@@ -124,14 +168,14 @@ void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset,
} else if (EntryExit == 2) {
assert(!Entries.empty() && Entries.back().IncludeOffset &&
"PPDirectives should have caught case when popping empty include stack");
-
+
// Get the include loc of the last entries' include loc as our include loc.
IncludeOffset = 0;
if (const LineEntry *PrevEntry =
FindNearestLineEntry(FID, Entries.back().IncludeOffset))
IncludeOffset = PrevEntry->IncludeOffset;
}
-
+
Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID, FileKind,
IncludeOffset));
}
@@ -139,7 +183,7 @@ void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset,
/// FindNearestLineEntry - Find the line entry nearest to FID that is before
/// it. If there is no line entry before Offset in FID, return null.
-const LineEntry *LineTableInfo::FindNearestLineEntry(unsigned FID,
+const LineEntry *LineTableInfo::FindNearestLineEntry(unsigned FID,
unsigned Offset) {
const std::vector<LineEntry> &Entries = LineEntries[FID];
assert(!Entries.empty() && "No #line entries for this FID after all!");
@@ -158,13 +202,13 @@ const LineEntry *LineTableInfo::FindNearestLineEntry(unsigned FID,
/// \brief Add a new line entry that has already been encoded into
/// the internal representation of the line table.
-void LineTableInfo::AddEntry(unsigned FID,
+void LineTableInfo::AddEntry(unsigned FID,
const std::vector<LineEntry> &Entries) {
LineEntries[FID] = Entries;
}
/// getLineTableFilenameID - Return the uniqued ID for the specified filename.
-///
+///
unsigned SourceManager::getLineTableFilenameID(const char *Ptr, unsigned Len) {
if (LineTable == 0)
LineTable = new LineTableInfo();
@@ -178,12 +222,12 @@ unsigned SourceManager::getLineTableFilenameID(const char *Ptr, unsigned Len) {
void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo,
int FilenameID) {
std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc);
-
+
const SrcMgr::FileInfo &FileInfo = getSLocEntry(LocInfo.first).getFile();
// Remember that this file has #line directives now if it doesn't already.
const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives();
-
+
if (LineTable == 0)
LineTable = new LineTableInfo();
LineTable->AddLineNote(LocInfo.first.ID, LocInfo.second, LineNo, FilenameID);
@@ -201,16 +245,16 @@ void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo,
"Can't set flags without setting the filename!");
return AddLineNote(Loc, LineNo, FilenameID);
}
-
+
std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc);
const SrcMgr::FileInfo &FileInfo = getSLocEntry(LocInfo.first).getFile();
-
+
// Remember that this file has #line directives now if it doesn't already.
const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives();
-
+
if (LineTable == 0)
LineTable = new LineTableInfo();
-
+
SrcMgr::CharacteristicKind FileKind;
if (IsExternCHeader)
FileKind = SrcMgr::C_ExternCSystem;
@@ -218,13 +262,13 @@ void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo,
FileKind = SrcMgr::C_System;
else
FileKind = SrcMgr::C_User;
-
+
unsigned EntryExit = 0;
if (IsFileEntry)
EntryExit = 1;
else if (IsFileExit)
EntryExit = 2;
-
+
LineTable->AddLineNote(LocInfo.first.ID, LocInfo.second, LineNo, FilenameID,
EntryExit, FileKind);
}
@@ -241,7 +285,7 @@ LineTableInfo &SourceManager::getLineTable() {
SourceManager::~SourceManager() {
delete LineTable;
-
+
// Delete FileEntry objects corresponding to content caches. Since the actual
// content cache objects are bump pointer allocated, we just have to run the
// dtors, but we call the deallocate method for completeness.
@@ -262,10 +306,10 @@ void SourceManager::clearIDTables() {
LastLineNoFileIDQuery = FileID();
LastLineNoContentCache = 0;
LastFileIDLookup = FileID();
-
+
if (LineTable)
LineTable->clear();
-
+
// Use up FileID #0 as an invalid instantiation.
NextOffset = 0;
createInstantiationLoc(SourceLocation(),SourceLocation(),SourceLocation(), 1);
@@ -276,11 +320,11 @@ void SourceManager::clearIDTables() {
const ContentCache *
SourceManager::getOrCreateContentCache(const FileEntry *FileEnt) {
assert(FileEnt && "Didn't specify a file entry to use?");
-
+
// Do we already have information about this file?
ContentCache *&Entry = FileInfos[FileEnt];
if (Entry) return Entry;
-
+
// Nope, create a new Cache entry. Make sure it is at least 8-byte aligned
// so that FileInfo can use the low 3 bits of the pointer for its own
// nefarious purposes.
@@ -288,6 +332,16 @@ SourceManager::getOrCreateContentCache(const FileEntry *FileEnt) {
EntryAlign = std::max(8U, EntryAlign);
Entry = ContentCacheAlloc.Allocate<ContentCache>(1, EntryAlign);
new (Entry) ContentCache(FileEnt);
+
+ if (FileEnt == TruncateFile) {
+ // If we had queued up a file truncation request, perform the truncation
+ // now.
+ Entry->truncateAt(TruncateAtLine, TruncateAtColumn);
+ TruncateFile = 0;
+ TruncateAtLine = 0;
+ TruncateAtColumn = 0;
+ }
+
return Entry;
}
@@ -350,12 +404,12 @@ FileID SourceManager::createFileID(const ContentCache *File,
if (PreallocatedID) {
// If we're filling in a preallocated ID, just load in the file
// entry and return.
- assert(PreallocatedID < SLocEntryLoaded.size() &&
+ assert(PreallocatedID < SLocEntryLoaded.size() &&
"Preallocate ID out-of-range");
- assert(!SLocEntryLoaded[PreallocatedID] &&
+ assert(!SLocEntryLoaded[PreallocatedID] &&
"Source location entry already loaded");
assert(Offset && "Preallocate source location cannot have zero offset");
- SLocEntryTable[PreallocatedID]
+ SLocEntryTable[PreallocatedID]
= SLocEntry::get(Offset, FileInfo::get(IncludePos, File, FileCharacter));
SLocEntryLoaded[PreallocatedID] = true;
FileID FID = FileID::get(PreallocatedID);
@@ -364,13 +418,13 @@ FileID SourceManager::createFileID(const ContentCache *File,
return LastFileIDLookup = FID;
}
- SLocEntryTable.push_back(SLocEntry::get(NextOffset,
+ SLocEntryTable.push_back(SLocEntry::get(NextOffset,
FileInfo::get(IncludePos, File,
FileCharacter)));
unsigned FileSize = File->getSize();
assert(NextOffset+FileSize+1 > NextOffset && "Ran out of source locations!");
NextOffset += FileSize+1;
-
+
// Set LastFileIDLookup to the newly created file. The next getFileID call is
// almost guaranteed to be from that file.
FileID FID = FileID::get(SLocEntryTable.size()-1);
@@ -392,9 +446,9 @@ SourceLocation SourceManager::createInstantiationLoc(SourceLocation SpellingLoc,
if (PreallocatedID) {
// If we're filling in a preallocated ID, just load in the
// instantiation entry and return.
- assert(PreallocatedID < SLocEntryLoaded.size() &&
+ assert(PreallocatedID < SLocEntryLoaded.size() &&
"Preallocate ID out-of-range");
- assert(!SLocEntryLoaded[PreallocatedID] &&
+ assert(!SLocEntryLoaded[PreallocatedID] &&
"Source location entry already loaded");
assert(Offset && "Preallocate source location cannot have zero offset");
SLocEntryTable[PreallocatedID] = SLocEntry::get(Offset, II);
@@ -427,7 +481,7 @@ SourceManager::getBufferData(FileID FID) const {
///
FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const {
assert(SLocOffset && "Invalid FileID");
-
+
// After the first and second level caches, I see two common sorts of
// behavior: 1) a lot of searched FileID's are "near" the cached file location
// or are "near" the cached instantiation location. 2) others are just
@@ -436,11 +490,11 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const {
// To handle this, we do a linear search for up to 8 steps to catch #1 quickly
// then we fall back to a less cache efficient, but more scalable, binary
// search to find the location.
-
+
// See if this is near the file point - worst case we start scanning from the
// most newly created FileID.
std::vector<SrcMgr::SLocEntry>::const_iterator I;
-
+
if (SLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset) {
// Neither loc prunes our search.
I = SLocEntryTable.end();
@@ -475,7 +529,7 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const {
if (++NumProbes == 8)
break;
}
-
+
// Convert "I" back into an index. We know that it is an entry whose index is
// larger than the offset we are looking for.
unsigned GreaterIndex = I-SLocEntryTable.begin();
@@ -487,16 +541,16 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const {
while (1) {
unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex;
unsigned MidOffset = getSLocEntry(FileID::get(MiddleIndex)).getOffset();
-
+
++NumProbes;
-
+
// If the offset of the midpoint is too large, chop the high side of the
// range to the midpoint.
if (MidOffset > SLocOffset) {
GreaterIndex = MiddleIndex;
continue;
}
-
+
// If the middle index contains the value, succeed and return.
if (isOffsetInFileID(FileID::get(MiddleIndex), SLocOffset)) {
#if 0
@@ -514,7 +568,7 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const {
NumBinaryProbes += NumProbes;
return Res;
}
-
+
// Otherwise, move the low-side up to the middle index.
LessIndex = MiddleIndex;
}
@@ -551,12 +605,12 @@ SourceManager::getDecomposedInstantiationLocSlowCase(const SrcMgr::SLocEntry *E,
SourceLocation Loc;
do {
Loc = E->getInstantiation().getInstantiationLocStart();
-
+
FID = getFileID(Loc);
E = &getSLocEntry(FID);
Offset += Loc.getOffset()-E->getOffset();
} while (!Loc.isFileID());
-
+
return std::make_pair(FID, Offset);
}
@@ -569,12 +623,12 @@ SourceManager::getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E,
SourceLocation Loc;
do {
Loc = E->getInstantiation().getSpellingLoc();
-
+
FID = getFileID(Loc);
E = &getSLocEntry(FID);
Offset += Loc.getOffset()-E->getOffset();
} while (!Loc.isFileID());
-
+
return std::make_pair(FID, Offset);
}
@@ -604,10 +658,10 @@ SourceManager::getImmediateInstantiationRange(SourceLocation Loc) const {
std::pair<SourceLocation,SourceLocation>
SourceManager::getInstantiationRange(SourceLocation Loc) const {
if (Loc.isFileID()) return std::make_pair(Loc, Loc);
-
+
std::pair<SourceLocation,SourceLocation> Res =
getImmediateInstantiationRange(Loc);
-
+
// Fully resolve the start and end locations to their ultimate instantiation
// points.
while (!Res.first.isFileID())
@@ -629,7 +683,7 @@ const char *SourceManager::getCharacterData(SourceLocation SL) const {
// Note that this is a hot function in the getSpelling() path, which is
// heavily used by -E mode.
std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(SL);
-
+
// Note that calling 'getBuffer()' may lazily page in a source file.
return getSLocEntry(LocInfo.first).getFile().getContentCache()
->getBuffer()->getBufferStart() + LocInfo.second;
@@ -640,7 +694,7 @@ const char *SourceManager::getCharacterData(SourceLocation SL) const {
/// this is significantly cheaper to compute than the line number.
unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos) const {
const char *Buf = getBuffer(FID)->getBufferStart();
-
+
unsigned LineStart = FilePos;
while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r')
--LineStart;
@@ -663,17 +717,17 @@ unsigned SourceManager::getInstantiationColumnNumber(SourceLocation Loc) const {
static void ComputeLineNumbers(ContentCache* FI,
llvm::BumpPtrAllocator &Alloc) DISABLE_INLINE;
-static void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc){
+static void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc){
// Note that calling 'getBuffer()' may lazily page in the file.
const MemoryBuffer *Buffer = FI->getBuffer();
-
+
// Find the file offsets of all of the *physical* source lines. This does
// not look at trigraphs, escaped newlines, or anything else tricky.
std::vector<unsigned> LineOffsets;
-
+
// Line #1 starts at char 0.
LineOffsets.push_back(0);
-
+
const unsigned char *Buf = (const unsigned char *)Buffer->getBufferStart();
const unsigned char *End = (const unsigned char *)Buffer->getBufferEnd();
unsigned Offs = 0;
@@ -686,7 +740,7 @@ static void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc){
++NextBuf;
Offs += NextBuf-Buf;
Buf = NextBuf;
-
+
if (Buf[0] == '\n' || Buf[0] == '\r') {
// If this is \n\r or \r\n, skip both characters.
if ((Buf[1] == '\n' || Buf[1] == '\r') && Buf[0] != Buf[1])
@@ -700,7 +754,7 @@ static void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc){
++Offs, ++Buf;
}
}
-
+
// Copy the offsets into the FileInfo structure.
FI->NumLines = LineOffsets.size();
FI->SourceLineCache = Alloc.Allocate<unsigned>(LineOffsets.size());
@@ -718,7 +772,7 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos) const {
else
Content = const_cast<ContentCache*>(getSLocEntry(FID)
.getFile().getContentCache());
-
+
// If this is the first use of line information for this buffer, compute the
/// SourceLineCache for it on demand.
if (Content->SourceLineCache == 0)
@@ -729,11 +783,11 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos) const {
unsigned *SourceLineCache = Content->SourceLineCache;
unsigned *SourceLineCacheStart = SourceLineCache;
unsigned *SourceLineCacheEnd = SourceLineCache + Content->NumLines;
-
+
unsigned QueriedFilePos = FilePos+1;
// FIXME: I would like to be convinced that this code is worth being as
- // complicated as it is, binary search isn't that slow.
+ // complicated as it is, binary search isn't that slow.
//
// If it is worth being optimized, then in my opinion it could be more
// performant, simpler, and more obviously correct by just "galloping" outward
@@ -749,7 +803,7 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos) const {
if (QueriedFilePos >= LastLineNoFilePos) {
// FIXME: Potential overflow?
SourceLineCache = SourceLineCache+LastLineNoResult-1;
-
+
// The query is likely to be nearby the previous one. Here we check to
// see if it is within 5, 10 or 20 lines. It can be far away in cases
// where big comment blocks and vertical whitespace eat up lines but
@@ -771,17 +825,17 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos) const {
SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
}
}
-
+
// If the spread is large, do a "radix" test as our initial guess, based on
// the assumption that lines average to approximately the same length.
// NOTE: This is currently disabled, as it does not appear to be profitable in
// initial measurements.
if (0 && SourceLineCacheEnd-SourceLineCache > 20) {
unsigned FileLen = Content->SourceLineCache[Content->NumLines-1];
-
+
// Take a stab at guessing where it is.
unsigned ApproxPos = Content->NumLines*QueriedFilePos / FileLen;
-
+
// Check for -10 and +10 lines.
unsigned LowerBound = std::max(int(ApproxPos-10), 0);
unsigned UpperBound = std::min(ApproxPos+10, FileLen);
@@ -790,17 +844,17 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos) const {
if (SourceLineCache < SourceLineCacheStart+LowerBound &&
SourceLineCacheStart[LowerBound] < QueriedFilePos)
SourceLineCache = SourceLineCacheStart+LowerBound;
-
+
// If the computed upper bound is greater than the query location, move it.
if (SourceLineCacheEnd > SourceLineCacheStart+UpperBound &&
SourceLineCacheStart[UpperBound] >= QueriedFilePos)
SourceLineCacheEnd = SourceLineCacheStart+UpperBound;
}
-
+
unsigned *Pos
= std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
unsigned LineNo = Pos-SourceLineCacheStart;
-
+
LastLineNoFileIDQuery = FID;
LastLineNoContentCache = Content;
LastLineNoFilePos = QueriedFilePos;
@@ -820,14 +874,14 @@ unsigned SourceManager::getSpellingLineNumber(SourceLocation Loc) const {
}
/// getFileCharacteristic - return the file characteristic of the specified
-/// source location, indicating whether this is a normal file, a system
+/// source location, indicating whether this is a normal file, a system
/// header, or an "implicit extern C" system header.
///
/// This state can be modified with flags on GNU linemarker directives like:
/// # 4 "foo.h" 3
/// which changes all source locations in the current file after that to be
/// considered to be from a system header.
-SrcMgr::CharacteristicKind
+SrcMgr::CharacteristicKind
SourceManager::getFileCharacteristic(SourceLocation Loc) const {
assert(!Loc.isInvalid() && "Can't get file characteristic of invalid loc!");
std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc);
@@ -837,12 +891,12 @@ SourceManager::getFileCharacteristic(SourceLocation Loc) const {
// state.
if (!FI.hasLineDirectives())
return FI.getFileCharacteristic();
-
+
assert(LineTable && "Can't have linetable entries without a LineTable!");
// See if there is a #line directive before the location.
const LineEntry *Entry =
LineTable->FindNearestLineEntry(LocInfo.first.ID, LocInfo.second);
-
+
// If this is before the first line marker, use the file characteristic.
if (!Entry)
return FI.getFileCharacteristic();
@@ -855,7 +909,7 @@ SourceManager::getFileCharacteristic(SourceLocation Loc) const {
/// for normal clients.
const char *SourceManager::getBufferName(SourceLocation Loc) const {
if (Loc.isInvalid()) return "<invalid loc>";
-
+
return getBuffer(getFileID(Loc))->getBufferIdentifier();
}
@@ -869,22 +923,22 @@ const char *SourceManager::getBufferName(SourceLocation Loc) const {
/// of an instantiation location, not at the spelling location.
PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const {
if (Loc.isInvalid()) return PresumedLoc();
-
+
// Presumed locations are always for instantiation points.
std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc);
-
+
const SrcMgr::FileInfo &FI = getSLocEntry(LocInfo.first).getFile();
const SrcMgr::ContentCache *C = FI.getContentCache();
-
+
// To get the source name, first consult the FileEntry (if one exists)
// before the MemBuffer as this will avoid unnecessarily paging in the
// MemBuffer.
- const char *Filename =
+ const char *Filename =
C->Entry ? C->Entry->getName() : C->getBuffer()->getBufferIdentifier();
unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second);
unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second);
SourceLocation IncludeLoc = FI.getIncludeLoc();
-
+
// If we have #line directives in this file, update and overwrite the physical
// location info if appropriate.
if (FI.hasLineDirectives()) {
@@ -902,9 +956,9 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const {
// total.
unsigned MarkerLineNo = getLineNumber(LocInfo.first, Entry->FileOffset);
LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1);
-
+
// Note that column numbers are not molested by line markers.
-
+
// Handle virtual #include manipulation.
if (Entry->IncludeOffset) {
IncludeLoc = getLocForStartOfFile(LocInfo.first);
@@ -933,7 +987,7 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile,
if (FI == FileInfos.end())
return SourceLocation();
ContentCache *Content = FI->second;
-
+
// If this is the first use of line information for this buffer, compute the
/// SourceLineCache for it on demand.
if (Content->SourceLineCache == 0)
@@ -941,7 +995,7 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile,
if (Line > Content->NumLines)
return SourceLocation();
-
+
unsigned FilePos = Content->SourceLineCache[Line - 1];
const char *Buf = Content->getBuffer()->getBufferStart() + FilePos;
unsigned BufLength = Content->getBuffer()->getBufferEnd() - Buf;
@@ -952,7 +1006,7 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile,
++i;
if (i < Col-1)
return SourceLocation();
-
+
return getLocForStartOfFile(Content->FirstFID).
getFileLocWithOffset(FilePos + Col - 1);
}
@@ -965,24 +1019,24 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
assert(LHS.isValid() && RHS.isValid() && "Passed invalid source location!");
if (LHS == RHS)
return false;
-
+
std::pair<FileID, unsigned> LOffs = getDecomposedLoc(LHS);
std::pair<FileID, unsigned> ROffs = getDecomposedLoc(RHS);
-
+
// If the source locations are in the same file, just compare offsets.
if (LOffs.first == ROffs.first)
return LOffs.second < ROffs.second;
// If we are comparing a source location with multiple locations in the same
// file, we get a big win by caching the result.
-
+
if (LastLFIDForBeforeTUCheck == LOffs.first &&
LastRFIDForBeforeTUCheck == ROffs.first)
return LastResForBeforeTUCheck;
-
+
LastLFIDForBeforeTUCheck = LOffs.first;
LastRFIDForBeforeTUCheck = ROffs.first;
-
+
// "Traverse" the include/instantiation stacks of both locations and try to
// find a common "ancestor".
//
@@ -1000,15 +1054,15 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
UpperLoc = Entry.getInstantiation().getInstantiationLocStart();
else
UpperLoc = Entry.getFile().getIncludeLoc();
-
+
if (UpperLoc.isInvalid())
break; // We reached the top.
-
+
ROffs = getDecomposedLoc(UpperLoc);
-
+
if (LOffs.first == ROffs.first)
return LastResForBeforeTUCheck = LOffs.second < ROffs.second;
-
+
ROffsMap[ROffs.first] = ROffs.second;
}
@@ -1022,33 +1076,33 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
UpperLoc = Entry.getInstantiation().getInstantiationLocStart();
else
UpperLoc = Entry.getFile().getIncludeLoc();
-
+
if (UpperLoc.isInvalid())
break; // We reached the top.
-
+
LOffs = getDecomposedLoc(UpperLoc);
-
+
std::map<FileID, unsigned>::iterator I = ROffsMap.find(LOffs.first);
if (I != ROffsMap.end())
return LastResForBeforeTUCheck = LOffs.second < I->second;
}
-
+
// No common ancestor.
// Now we are getting into murky waters. Most probably this is because one
// location is in the predefines buffer.
-
+
const FileEntry *LEntry =
getSLocEntry(LOffs.first).getFile().getContentCache()->Entry;
const FileEntry *REntry =
getSLocEntry(ROffs.first).getFile().getContentCache()->Entry;
-
+
// If the locations are in two memory buffers we give up, we can't answer
// which one should be considered first.
// FIXME: Should there be a way to "include" memory buffers in the translation
// unit ?
assert((LEntry != 0 || REntry != 0) && "Locations in memory buffers.");
(void) REntry;
-
+
// Consider the memory buffer as coming before the file in the translation
// unit.
if (LEntry == 0)
@@ -1059,26 +1113,48 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
}
}
+void SourceManager::truncateFileAt(const FileEntry *Entry, unsigned Line,
+ unsigned Column) {
+ llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>::iterator FI
+ = FileInfos.find(Entry);
+ if (FI != FileInfos.end()) {
+ FI->second->truncateAt(Line, Column);
+ return;
+ }
+
+ // We cannot perform the truncation until we actually see the file, so
+ // save the truncation information.
+ assert(TruncateFile == 0 && "Can't queue up multiple file truncations!");
+ TruncateFile = Entry;
+ TruncateAtLine = Line;
+ TruncateAtColumn = Column;
+}
+
+/// \brief Determine whether this file was truncated.
+bool SourceManager::isTruncatedFile(FileID FID) const {
+ return getSLocEntry(FID).getFile().getContentCache()->isTruncated();
+}
+
/// PrintStats - Print statistics to stderr.
///
void SourceManager::PrintStats() const {
- llvm::cerr << "\n*** Source Manager Stats:\n";
- llvm::cerr << FileInfos.size() << " files mapped, " << MemBufferInfos.size()
- << " mem buffers mapped.\n";
- llvm::cerr << SLocEntryTable.size() << " SLocEntry's allocated, "
- << NextOffset << "B of Sloc address space used.\n";
-
+ llvm::errs() << "\n*** Source Manager Stats:\n";
+ llvm::errs() << FileInfos.size() << " files mapped, " << MemBufferInfos.size()
+ << " mem buffers mapped.\n";
+ llvm::errs() << SLocEntryTable.size() << " SLocEntry's allocated, "
+ << NextOffset << "B of Sloc address space used.\n";
+
unsigned NumLineNumsComputed = 0;
unsigned NumFileBytesMapped = 0;
for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){
NumLineNumsComputed += I->second->SourceLineCache != 0;
NumFileBytesMapped += I->second->getSizeBytesMapped();
}
-
- llvm::cerr << NumFileBytesMapped << " bytes of files mapped, "
- << NumLineNumsComputed << " files with line #'s computed.\n";
- llvm::cerr << "FileID scans: " << NumLinearScans << " linear, "
- << NumBinaryProbes << " binary.\n";
+
+ llvm::errs() << NumFileBytesMapped << " bytes of files mapped, "
+ << NumLineNumsComputed << " files with line #'s computed.\n";
+ llvm::errs() << "FileID scans: " << NumLinearScans << " linear, "
+ << NumBinaryProbes << " binary.\n";
}
ExternalSLocEntrySource::~ExternalSLocEntrySource() { }
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index ba7f190408b29..9cd12493e7a49 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -25,6 +25,8 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
TLSSupported = true;
PointerWidth = PointerAlign = 32;
WCharWidth = WCharAlign = 32;
+ Char16Width = Char16Align = 16;
+ Char32Width = Char32Align = 32;
IntWidth = IntAlign = 32;
LongWidth = LongAlign = 32;
LongLongWidth = LongLongAlign = 64;
@@ -41,6 +43,8 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
UIntMaxType = UnsignedLongLong;
IntPtrType = SignedLong;
WCharType = SignedInt;
+ Char16Type = UnsignedShort;
+ Char32Type = UnsignedInt;
Int64Type = SignedLongLong;
FloatFormat = &llvm::APFloat::IEEEsingle;
DoubleFormat = &llvm::APFloat::IEEEdouble;
@@ -83,17 +87,17 @@ static void removeGCCRegisterPrefix(const char *&Name) {
bool TargetInfo::isValidGCCRegisterName(const char *Name) const {
const char * const *Names;
unsigned NumNames;
-
+
// Get rid of any register prefix.
removeGCCRegisterPrefix(Name);
-
+
if (strcmp(Name, "memory") == 0 ||
strcmp(Name, "cc") == 0)
return true;
-
+
getGCCRegNames(Names, NumNames);
-
+
// If we have a number it maps to an entry in the register name array.
if (isdigit(Name[0])) {
char *End;
@@ -107,11 +111,11 @@ bool TargetInfo::isValidGCCRegisterName(const char *Name) const {
if (strcmp(Name, Names[i]) == 0)
return true;
}
-
+
// Now check aliases.
const GCCRegAlias *Aliases;
unsigned NumAliases;
-
+
getGCCRegAliases(Aliases, NumAliases);
for (unsigned i = 0; i < NumAliases; i++) {
for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
@@ -121,15 +125,15 @@ bool TargetInfo::isValidGCCRegisterName(const char *Name) const {
return true;
}
}
-
+
return false;
}
const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const {
assert(isValidGCCRegisterName(Name) && "Invalid register passed in");
-
+
removeGCCRegisterPrefix(Name);
-
+
const char * const *Names;
unsigned NumNames;
@@ -140,16 +144,16 @@ const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const {
char *End;
int n = (int)strtol(Name, &End, 0);
if (*End == 0) {
- assert(n >= 0 && (unsigned)n < NumNames &&
+ assert(n >= 0 && (unsigned)n < NumNames &&
"Out of bounds register number!");
return Names[n];
}
}
-
+
// Now check aliases.
const GCCRegAlias *Aliases;
unsigned NumAliases;
-
+
getGCCRegAliases(Aliases, NumAliases);
for (unsigned i = 0; i < NumAliases; i++) {
for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
@@ -159,7 +163,7 @@ const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const {
return Aliases[i].Register;
}
}
-
+
return Name;
}
@@ -184,6 +188,9 @@ bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const {
}
case '&': // early clobber.
break;
+ case '%': // commutative.
+ // FIXME: Check that there is a another register after this one.
+ break;
case 'r': // general register.
Info.setAllowsRegister();
break;
@@ -196,10 +203,10 @@ bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const {
Info.setAllowsMemory();
break;
}
-
+
Name++;
}
-
+
return true;
}
@@ -212,14 +219,14 @@ bool TargetInfo::resolveSymbolicName(const char *&Name,
const char *Start = Name;
while (*Name && *Name != ']')
Name++;
-
+
if (!*Name) {
// Missing ']'
return false;
}
-
+
std::string SymbolicName(Start, Name - Start);
-
+
for (Index = 0; Index != NumOutputs; ++Index)
if (SymbolicName == OutputConstraints[Index].getName())
return true;
@@ -238,12 +245,12 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints,
// Check if we have a matching constraint
if (*Name >= '0' && *Name <= '9') {
unsigned i = *Name - '0';
-
+
// Check if matching constraint is out of bounds.
if (i >= NumOutputs)
return false;
-
- // The constraint should have the same info as the respective
+
+ // The constraint should have the same info as the respective
// output constraint.
Info.setTiedOperand(i, OutputConstraints[i]);
} else if (!validateAsmConstraint(Name, Info)) {
@@ -257,9 +264,9 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints,
unsigned Index = 0;
if (!resolveSymbolicName(Name, OutputConstraints, NumOutputs, Index))
return false;
-
+
break;
- }
+ }
case '%': // commutative
// FIXME: Fail if % is used with the last operand.
break;
@@ -287,9 +294,9 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints,
Info.setAllowsMemory();
break;
}
-
+
Name++;
}
-
+
return true;
}
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 3f7d9a31c61e9..1d4d1235c9634 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -16,22 +16,25 @@
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/LangOptions.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/MC/MCSectionMachO.h"
using namespace clang;
//===----------------------------------------------------------------------===//
// Common code shared among targets.
//===----------------------------------------------------------------------===//
-static void Define(std::vector<char> &Buf, const char *Macro,
- const char *Val = "1") {
+static void Define(std::vector<char> &Buf, const llvm::StringRef &Macro,
+ const llvm::StringRef &Val = "1") {
const char *Def = "#define ";
Buf.insert(Buf.end(), Def, Def+strlen(Def));
- Buf.insert(Buf.end(), Macro, Macro+strlen(Macro));
+ Buf.insert(Buf.end(), Macro.begin(), Macro.end());
Buf.push_back(' ');
- Buf.insert(Buf.end(), Val, Val+strlen(Val));
+ Buf.insert(Buf.end(), Val.begin(), Val.end());
Buf.push_back('\n');
}
@@ -51,91 +54,34 @@ static void DefineStd(std::vector<char> &Buf, const char *MacroName,
llvm::SmallString<20> TmpStr;
TmpStr = "__";
TmpStr += MacroName;
- Define(Buf, TmpStr.c_str());
+ Define(Buf, TmpStr.str());
// Define __unix__.
TmpStr += "__";
- Define(Buf, TmpStr.c_str());
+ Define(Buf, TmpStr.str());
}
//===----------------------------------------------------------------------===//
// Defines specific to certain operating systems.
//===----------------------------------------------------------------------===//
+
namespace {
template<typename TgtInfo>
class OSTargetInfo : public TgtInfo {
protected:
- virtual void getOSDefines(const LangOptions &Opts, const char *Triple,
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
std::vector<char> &Defines) const=0;
public:
OSTargetInfo(const std::string& triple) : TgtInfo(triple) {}
virtual void getTargetDefines(const LangOptions &Opts,
std::vector<char> &Defines) const {
TgtInfo::getTargetDefines(Opts, Defines);
- getOSDefines(Opts, TgtInfo::getTargetTriple(), Defines);
+ getOSDefines(Opts, TgtInfo::getTriple(), Defines);
}
};
-}
-
-namespace {
-/// getDarwinNumber - Parse the 'darwin number' out of the specific targe
-/// triple. For example, if we have darwin8.5 return 8,5,0. If any entry is
-/// not defined, return 0's. Return true if we have -darwin in the string or
-/// false otherwise.
-static bool getDarwinNumber(const char *Triple, unsigned &Maj, unsigned &Min, unsigned &Revision) {
- Maj = Min = Revision = 0;
- const char *Darwin = strstr(Triple, "-darwin");
- if (Darwin == 0) return false;
-
- Darwin += strlen("-darwin");
- if (Darwin[0] < '0' || Darwin[0] > '9')
- return true;
-
- Maj = Darwin[0]-'0';
- ++Darwin;
-
- // Handle "darwin11".
- if (Maj == 1 && Darwin[0] >= '0' && Darwin[0] <= '9') {
- Maj = Maj*10 + (Darwin[0] - '0');
- ++Darwin;
- }
-
- // Handle minor version: 10.4.9 -> darwin8.9 -> "1049"
- if (Darwin[0] != '.')
- return true;
-
- ++Darwin;
- if (Darwin[0] < '0' || Darwin[0] > '9')
- return true;
-
- Min = Darwin[0]-'0';
- ++Darwin;
-
- // Handle 10.4.11 -> darwin8.11
- if (Min == 1 && Darwin[0] >= '0' && Darwin[0] <= '9') {
- Min = Min*10 + (Darwin[0] - '0');
- ++Darwin;
- }
-
- // Handle revision darwin8.9.1
- if (Darwin[0] != '.')
- return true;
-
- ++Darwin;
- if (Darwin[0] < '0' || Darwin[0] > '9')
- return true;
-
- Revision = Darwin[0]-'0';
- ++Darwin;
-
- if (Revision == 1 && Darwin[0] >= '0' && Darwin[0] <= '9') {
- Revision = Revision*10 + (Darwin[0] - '0');
- ++Darwin;
- }
+} // end anonymous namespace
- return true;
-}
static void getDarwinDefines(std::vector<char> &Defs, const LangOptions &Opts) {
Define(Defs, "__APPLE_CC__", "5621");
@@ -156,81 +102,94 @@ static void getDarwinDefines(std::vector<char> &Defs, const LangOptions &Opts) {
Define(Defs, "__STATIC__");
else
Define(Defs, "__DYNAMIC__");
+
+ if (Opts.POSIXThreads)
+ Define(Defs, "_REENTRANT", "1");
}
-static void getDarwinOSXDefines(std::vector<char> &Defs, const char *Triple) {
+static void getDarwinOSXDefines(std::vector<char> &Defs,
+ const llvm::Triple &Triple) {
+ if (Triple.getOS() != llvm::Triple::Darwin)
+ return;
+
// Figure out which "darwin number" the target triple is. "darwin9" -> 10.5.
unsigned Maj, Min, Rev;
- if (getDarwinNumber(Triple, Maj, Min, Rev)) {
- char MacOSXStr[] = "1000";
- if (Maj >= 4 && Maj <= 13) { // 10.0-10.9
- // darwin7 -> 1030, darwin8 -> 1040, darwin9 -> 1050, etc.
- MacOSXStr[2] = '0' + Maj-4;
- }
+ Triple.getDarwinNumber(Maj, Min, Rev);
- // Handle minor version: 10.4.9 -> darwin8.9 -> "1049"
- // Cap 10.4.11 -> darwin8.11 -> "1049"
- MacOSXStr[3] = std::min(Min, 9U)+'0';
- Define(Defs, "__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", MacOSXStr);
+ char MacOSXStr[] = "1000";
+ if (Maj >= 4 && Maj <= 13) { // 10.0-10.9
+ // darwin7 -> 1030, darwin8 -> 1040, darwin9 -> 1050, etc.
+ MacOSXStr[2] = '0' + Maj-4;
}
+
+ // Handle minor version: 10.4.9 -> darwin8.9 -> "1049"
+ // Cap 10.4.11 -> darwin8.11 -> "1049"
+ MacOSXStr[3] = std::min(Min, 9U)+'0';
+ Define(Defs, "__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", MacOSXStr);
}
static void getDarwinIPhoneOSDefines(std::vector<char> &Defs,
- const char *Triple) {
+ const llvm::Triple &Triple) {
+ if (Triple.getOS() != llvm::Triple::Darwin)
+ return;
+
// Figure out which "darwin number" the target triple is. "darwin9" -> 10.5.
unsigned Maj, Min, Rev;
- if (getDarwinNumber(Triple, Maj, Min, Rev)) {
- // When targetting iPhone OS, interpret the minor version and
- // revision as the iPhone OS version
- char iPhoneOSStr[] = "10000";
- if (Min >= 2 && Min <= 9) { // iPhone OS 2.0-9.0
- // darwin9.2.0 -> 20000, darwin9.3.0 -> 30000, etc.
- iPhoneOSStr[0] = '0' + Min;
- }
+ Triple.getDarwinNumber(Maj, Min, Rev);
- // Handle minor version: 2.2 -> darwin9.2.2 -> 20200
- iPhoneOSStr[2] = std::min(Rev, 9U)+'0';
- Define(Defs, "__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__",
- iPhoneOSStr);
+ // When targetting iPhone OS, interpret the minor version and
+ // revision as the iPhone OS version
+ char iPhoneOSStr[] = "10000";
+ if (Min >= 2 && Min <= 9) { // iPhone OS 2.0-9.0
+ // darwin9.2.0 -> 20000, darwin9.3.0 -> 30000, etc.
+ iPhoneOSStr[0] = '0' + Min;
}
+
+ // Handle minor version: 2.2 -> darwin9.2.2 -> 20200
+ iPhoneOSStr[2] = std::min(Rev, 9U)+'0';
+ Define(Defs, "__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__",
+ iPhoneOSStr);
}
/// GetDarwinLanguageOptions - Set the default language options for darwin.
static void GetDarwinLanguageOptions(LangOptions &Opts,
- const char *Triple) {
+ const llvm::Triple &Triple) {
Opts.NeXTRuntime = true;
- unsigned Maj, Min, Rev;
- if (!getDarwinNumber(Triple, Maj, Min, Rev))
+ if (Triple.getOS() != llvm::Triple::Darwin)
return;
+ unsigned MajorVersion = Triple.getDarwinMajorNumber();
+
// Blocks and stack protectors default to on for 10.6 (darwin10) and beyond.
- if (Maj > 9) {
+ if (MajorVersion > 9) {
Opts.Blocks = 1;
Opts.setStackProtectorMode(LangOptions::SSPOn);
}
// Non-fragile ABI (in 64-bit mode) default to on for 10.5 (darwin9) and
// beyond.
- if (Maj >= 9 && Opts.ObjC1 && !strncmp(Triple, "x86_64", 6))
+ if (MajorVersion >= 9 && Opts.ObjC1 &&
+ Triple.getArch() == llvm::Triple::x86_64)
Opts.ObjCNonFragileABI = 1;
}
+namespace {
template<typename Target>
class DarwinTargetInfo : public OSTargetInfo<Target> {
protected:
- virtual void getOSDefines(const LangOptions &Opts, const char *Triple,
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
std::vector<char> &Defines) const {
getDarwinDefines(Defines, Opts);
getDarwinOSXDefines(Defines, Triple);
}
-
+
/// getDefaultLangOptions - Allow the target to specify default settings for
/// various language options. These may be overridden by command line
/// options.
virtual void getDefaultLangOptions(LangOptions &Opts) {
TargetInfo::getDefaultLangOptions(Opts);
- GetDarwinLanguageOptions(Opts, TargetInfo::getTargetTriple());
+ GetDarwinLanguageOptions(Opts, TargetInfo::getTriple());
}
public:
DarwinTargetInfo(const std::string& triple) :
@@ -238,28 +197,25 @@ public:
this->TLSSupported = false;
}
- virtual const char *getCFStringSymbolPrefix() const {
- return "\01L_unnamed_cfstring_";
- }
-
- virtual const char *getStringSymbolPrefix(bool IsConstant) const {
- return IsConstant ? "\01LC" : "\01lC";
- }
-
- virtual const char *getUnicodeStringSymbolPrefix() const {
- return "__utf16_string_";
- }
-
virtual const char *getUnicodeStringSection() const {
return "__TEXT,__ustring";
}
+
+ virtual std::string isValidSectionSpecifier(const llvm::StringRef &SR) const {
+ // Let MCSectionMachO validate this.
+ llvm::StringRef Segment, Section;
+ unsigned TAA, StubSize;
+ return llvm::MCSectionMachO::ParseSectionSpecifier(SR, Segment, Section,
+ TAA, StubSize);
+ }
};
+
// DragonFlyBSD Target
template<typename Target>
class DragonFlyBSDTargetInfo : public OSTargetInfo<Target> {
protected:
- virtual void getOSDefines(const LangOptions &Opts, const char *Triple,
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
std::vector<char> &Defs) const {
// DragonFly defines; list based off of gcc output
Define(Defs, "__DragonFly__");
@@ -270,7 +226,7 @@ protected:
DefineStd(Defs, "unix", Opts);
}
public:
- DragonFlyBSDTargetInfo(const std::string &triple)
+ DragonFlyBSDTargetInfo(const std::string &triple)
: OSTargetInfo<Target>(triple) {}
};
@@ -278,11 +234,13 @@ public:
template<typename Target>
class FreeBSDTargetInfo : public OSTargetInfo<Target> {
protected:
- virtual void getOSDefines(const LangOptions &Opts, const char *Triple,
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
std::vector<char> &Defs) const {
// FreeBSD defines; list based off of gcc output
- const char *FreeBSD = strstr(Triple, "-freebsd");
+ // FIXME: Move version number handling to llvm::Triple.
+ const char *FreeBSD = strstr(Triple.getTriple().c_str(),
+ "-freebsd");
FreeBSD += strlen("-freebsd");
char release[] = "X";
release[0] = FreeBSD[0];
@@ -296,43 +254,69 @@ protected:
Define(Defs, "__ELF__", "1");
}
public:
- FreeBSDTargetInfo(const std::string &triple)
- : OSTargetInfo<Target>(triple) {}
+ FreeBSDTargetInfo(const std::string &triple)
+ : OSTargetInfo<Target>(triple) {
+ this->UserLabelPrefix = "";
+ }
};
// Linux target
template<typename Target>
class LinuxTargetInfo : public OSTargetInfo<Target> {
protected:
- virtual void getOSDefines(const LangOptions &Opts, const char *Triple,
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
std::vector<char> &Defs) const {
// Linux defines; list based off of gcc output
DefineStd(Defs, "unix", Opts);
DefineStd(Defs, "linux", Opts);
Define(Defs, "__gnu_linux__");
Define(Defs, "__ELF__", "1");
+ if (Opts.POSIXThreads)
+ Define(Defs, "_REENTRANT", "1");
}
public:
- LinuxTargetInfo(const std::string& triple)
+ LinuxTargetInfo(const std::string& triple)
: OSTargetInfo<Target>(triple) {
this->UserLabelPrefix = "";
}
};
+// NetBSD Target
+template<typename Target>
+class NetBSDTargetInfo : public OSTargetInfo<Target> {
+protected:
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ std::vector<char> &Defs) const {
+ // NetBSD defines; list based off of gcc output
+ Define(Defs, "__NetBSD__", "1");
+ Define(Defs, "__unix__", "1");
+ Define(Defs, "__ELF__", "1");
+ if (Opts.POSIXThreads)
+ Define(Defs, "_POSIX_THREADS", "1");
+ }
+public:
+ NetBSDTargetInfo(const std::string &triple)
+ : OSTargetInfo<Target>(triple) {
+ this->UserLabelPrefix = "";
+ }
+};
+
// OpenBSD Target
template<typename Target>
class OpenBSDTargetInfo : public OSTargetInfo<Target> {
protected:
- virtual void getOSDefines(const LangOptions &Opts, const char *Triple,
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
std::vector<char> &Defs) const {
// OpenBSD defines; list based off of gcc output
Define(Defs, "__OpenBSD__", "1");
DefineStd(Defs, "unix", Opts);
Define(Defs, "__ELF__", "1");
+ if (Opts.POSIXThreads)
+ Define(Defs, "_POSIX_THREADS", "1");
}
public:
- OpenBSDTargetInfo(const std::string &triple)
+ OpenBSDTargetInfo(const std::string &triple)
: OSTargetInfo<Target>(triple) {}
};
@@ -340,7 +324,7 @@ public:
template<typename Target>
class SolarisTargetInfo : public OSTargetInfo<Target> {
protected:
- virtual void getOSDefines(const LangOptions &Opts, const char *Triple,
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
std::vector<char> &Defs) const {
DefineStd(Defs, "sun", Opts);
DefineStd(Defs, "unix", Opts);
@@ -349,20 +333,14 @@ protected:
Define(Defs, "__SVR4");
}
public:
- SolarisTargetInfo(const std::string& triple)
+ SolarisTargetInfo(const std::string& triple)
: OSTargetInfo<Target>(triple) {
this->UserLabelPrefix = "";
this->WCharType = this->SignedLong;
// FIXME: WIntType should be SignedLong
}
};
-} // end anonymous namespace.
-
-/// GetWindowsLanguageOptions - Set the default language options for Windows.
-static void GetWindowsLanguageOptions(LangOptions &Opts,
- const char *Triple) {
- Opts.Microsoft = true;
-}
+} // end anonymous namespace.
//===----------------------------------------------------------------------===//
// Specific target implementations.
@@ -398,9 +376,6 @@ public:
" void* reg_save_area;"
"} __builtin_va_list[1];";*/
}
- virtual const char *getTargetPrefix() const {
- return "ppc";
- }
virtual void getGCCRegNames(const char * const *&Names,
unsigned &NumNames) const;
virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
@@ -464,21 +439,21 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
const char * const PPCTargetInfo::GCCRegNames[] = {
- "0", "1", "2", "3", "4", "5", "6", "7",
- "8", "9", "10", "11", "12", "13", "14", "15",
- "16", "17", "18", "19", "20", "21", "22", "23",
- "24", "25", "26", "27", "28", "29", "30", "31",
- "0", "1", "2", "3", "4", "5", "6", "7",
- "8", "9", "10", "11", "12", "13", "14", "15",
- "16", "17", "18", "19", "20", "21", "22", "23",
- "24", "25", "26", "27", "28", "29", "30", "31",
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
"mq", "lr", "ctr", "ap",
- "0", "1", "2", "3", "4", "5", "6", "7",
+ "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
"xer",
- "0", "1", "2", "3", "4", "5", "6", "7",
- "8", "9", "10", "11", "12", "13", "14", "15",
- "16", "17", "18", "19", "20", "21", "22", "23",
- "24", "25", "26", "27", "28", "29", "30", "31",
+ "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
+ "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
+ "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
+ "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
"vrsave", "vscr",
"spe_acc", "spefscr",
"sfp"
@@ -493,38 +468,71 @@ void PPCTargetInfo::getGCCRegNames(const char * const *&Names,
const TargetInfo::GCCRegAlias PPCTargetInfo::GCCRegAliases[] = {
// While some of these aliases do map to different registers
// they still share the same register name.
- { { "cc", "cr0", "fr0", "r0", "v0"}, "0" },
- { { "cr1", "fr1", "r1", "sp", "v1"}, "1" },
- { { "cr2", "fr2", "r2", "toc", "v2"}, "2" },
- { { "cr3", "fr3", "r3", "v3"}, "3" },
- { { "cr4", "fr4", "r4", "v4"}, "4" },
- { { "cr5", "fr5", "r5", "v5"}, "5" },
- { { "cr6", "fr6", "r6", "v6"}, "6" },
- { { "cr7", "fr7", "r7", "v7"}, "7" },
- { { "fr8", "r8", "v8"}, "8" },
- { { "fr9", "r9", "v9"}, "9" },
- { { "fr10", "r10", "v10"}, "10" },
- { { "fr11", "r11", "v11"}, "11" },
- { { "fr12", "r12", "v12"}, "12" },
- { { "fr13", "r13", "v13"}, "13" },
- { { "fr14", "r14", "v14"}, "14" },
- { { "fr15", "r15", "v15"}, "15" },
- { { "fr16", "r16", "v16"}, "16" },
- { { "fr17", "r17", "v17"}, "17" },
- { { "fr18", "r18", "v18"}, "18" },
- { { "fr19", "r19", "v19"}, "19" },
- { { "fr20", "r20", "v20"}, "20" },
- { { "fr21", "r21", "v21"}, "21" },
- { { "fr22", "r22", "v22"}, "22" },
- { { "fr23", "r23", "v23"}, "23" },
- { { "fr24", "r24", "v24"}, "24" },
- { { "fr25", "r25", "v25"}, "25" },
- { { "fr26", "r26", "v26"}, "26" },
- { { "fr27", "r27", "v27"}, "27" },
- { { "fr28", "r28", "v28"}, "28" },
- { { "fr29", "r29", "v29"}, "29" },
- { { "fr30", "r30", "v30"}, "30" },
- { { "fr31", "r31", "v31"}, "31" },
+ { { "0" }, "r0" },
+ { { "1"}, "r1" },
+ { { "2" }, "r2" },
+ { { "3" }, "r3" },
+ { { "4" }, "r4" },
+ { { "5" }, "r5" },
+ { { "6" }, "r6" },
+ { { "7" }, "r7" },
+ { { "8" }, "r8" },
+ { { "9" }, "r9" },
+ { { "10" }, "r10" },
+ { { "11" }, "r11" },
+ { { "12" }, "r12" },
+ { { "13" }, "r13" },
+ { { "14" }, "r14" },
+ { { "15" }, "r15" },
+ { { "16" }, "r16" },
+ { { "17" }, "r17" },
+ { { "18" }, "r18" },
+ { { "19" }, "r19" },
+ { { "20" }, "r20" },
+ { { "21" }, "r21" },
+ { { "22" }, "r22" },
+ { { "23" }, "r23" },
+ { { "24" }, "r24" },
+ { { "25" }, "r25" },
+ { { "26" }, "r26" },
+ { { "27" }, "r27" },
+ { { "28" }, "r28" },
+ { { "29" }, "r29" },
+ { { "30" }, "r30" },
+ { { "31" }, "r31" },
+ { { "fr0" }, "f0" },
+ { { "fr1" }, "f1" },
+ { { "fr2" }, "f2" },
+ { { "fr3" }, "f3" },
+ { { "fr4" }, "f4" },
+ { { "fr5" }, "f5" },
+ { { "fr6" }, "f6" },
+ { { "fr7" }, "f7" },
+ { { "fr8" }, "f8" },
+ { { "fr9" }, "f9" },
+ { { "fr10" }, "f10" },
+ { { "fr11" }, "f11" },
+ { { "fr12" }, "f12" },
+ { { "fr13" }, "f13" },
+ { { "fr14" }, "f14" },
+ { { "fr15" }, "f15" },
+ { { "fr16" }, "f16" },
+ { { "fr17" }, "f17" },
+ { { "fr18" }, "f18" },
+ { { "fr19" }, "f19" },
+ { { "fr20" }, "f20" },
+ { { "fr21" }, "f21" },
+ { { "fr22" }, "f22" },
+ { { "fr23" }, "f23" },
+ { { "fr24" }, "f24" },
+ { { "fr25" }, "f25" },
+ { { "fr26" }, "f26" },
+ { { "fr27" }, "f27" },
+ { { "fr28" }, "f28" },
+ { { "fr29" }, "f29" },
+ { { "fr30" }, "f30" },
+ { { "fr31" }, "f31" },
+ { { "cc" }, "cr0" },
};
void PPCTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
@@ -603,9 +611,6 @@ public:
Records = BuiltinInfo;
NumRecords = clang::X86::LastTSBuiltin-Builtin::FirstTSBuiltin;
}
- virtual const char *getTargetPrefix() const {
- return "x86";
- }
virtual void getGCCRegNames(const char * const *&Names,
unsigned &NumNames) const {
Names = GCCRegNames;
@@ -627,12 +632,12 @@ public:
virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features,
const std::string &Name,
bool Enabled) const;
- virtual void getDefaultFeatures(const std::string &CPU,
+ virtual void getDefaultFeatures(const std::string &CPU,
llvm::StringMap<bool> &Features) const;
virtual void HandleTargetFeatures(const llvm::StringMap<bool> &Features);
};
-void X86TargetInfo::getDefaultFeatures(const std::string &CPU,
+void X86TargetInfo::getDefaultFeatures(const std::string &CPU,
llvm::StringMap<bool> &Features) const {
// FIXME: This should not be here.
Features["3dnow"] = false;
@@ -676,7 +681,7 @@ void X86TargetInfo::getDefaultFeatures(const std::string &CPU,
setFeatureEnabled(Features, "sse4", true);
else if (CPU == "k6" || CPU == "winchip-c6")
setFeatureEnabled(Features, "mmx", true);
- else if (CPU == "k6-2" || CPU == "k6-3" || CPU == "athlon" ||
+ else if (CPU == "k6-2" || CPU == "k6-3" || CPU == "athlon" ||
CPU == "athlon-tbird" || CPU == "winchip2" || CPU == "c3") {
setFeatureEnabled(Features, "mmx", true);
setFeatureEnabled(Features, "3dnow", true);
@@ -685,14 +690,14 @@ void X86TargetInfo::getDefaultFeatures(const std::string &CPU,
setFeatureEnabled(Features, "3dnowa", true);
} else if (CPU == "k8" || CPU == "opteron" || CPU == "athlon64" ||
CPU == "athlon-fx") {
- setFeatureEnabled(Features, "sse2", true);
+ setFeatureEnabled(Features, "sse2", true);
setFeatureEnabled(Features, "3dnowa", true);
} else if (CPU == "c3-2")
setFeatureEnabled(Features, "sse", true);
}
bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
- const std::string &Name,
+ const std::string &Name,
bool Enabled) const {
// FIXME: This *really* should not be here.
if (!Features.count(Name) && Name != "sse4")
@@ -706,13 +711,13 @@ bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
else if (Name == "sse2")
Features["mmx"] = Features["sse"] = Features["sse2"] = true;
else if (Name == "sse3")
- Features["mmx"] = Features["sse"] = Features["sse2"] =
+ Features["mmx"] = Features["sse"] = Features["sse2"] =
Features["sse3"] = true;
else if (Name == "ssse3")
- Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] =
+ Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] =
Features["ssse3"] = true;
else if (Name == "sse4")
- Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] =
+ Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] =
Features["ssse3"] = Features["sse41"] = Features["sse42"] = true;
else if (Name == "3dnow")
Features["3dnowa"] = true;
@@ -720,16 +725,16 @@ bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
Features["3dnow"] = Features["3dnowa"] = true;
} else {
if (Name == "mmx")
- Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] =
+ Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] =
Features["ssse3"] = Features["sse41"] = Features["sse42"] = false;
else if (Name == "sse")
- Features["sse"] = Features["sse2"] = Features["sse3"] =
+ Features["sse"] = Features["sse2"] = Features["sse3"] =
Features["ssse3"] = Features["sse41"] = Features["sse42"] = false;
else if (Name == "sse2")
- Features["sse2"] = Features["sse3"] = Features["ssse3"] =
+ Features["sse2"] = Features["sse3"] = Features["ssse3"] =
Features["sse41"] = Features["sse42"] = false;
else if (Name == "sse3")
- Features["sse3"] = Features["ssse3"] = Features["sse41"] =
+ Features["sse3"] = Features["ssse3"] = Features["sse41"] =
Features["sse42"] = false;
else if (Name == "ssse3")
Features["ssse3"] = Features["sse41"] = Features["sse42"] = false;
@@ -885,6 +890,24 @@ public:
virtual const char *getVAListDeclaration() const {
return "typedef char* __builtin_va_list;";
}
+
+ int getEHDataRegisterNumber(unsigned RegNo) const {
+ if (RegNo == 0) return 0;
+ if (RegNo == 1) return 2;
+ return -1;
+ }
+};
+} // end anonymous namespace
+
+namespace {
+class OpenBSDI386TargetInfo : public OpenBSDTargetInfo<X86_32TargetInfo> {
+public:
+ OpenBSDI386TargetInfo(const std::string& triple) :
+ OpenBSDTargetInfo<X86_32TargetInfo>(triple) {
+ SizeType = UnsignedLong;
+ IntPtrType = SignedLong;
+ PtrDiffType = SignedLong;
+ }
};
} // end anonymous namespace
@@ -927,12 +950,75 @@ public:
DefineStd(Defines, "WIN32", Opts);
DefineStd(Defines, "WINNT", Opts);
Define(Defines, "_X86_");
- Define(Defines, "__MSVCRT__");
}
+};
+} // end anonymous namespace
+namespace {
+
+/// GetWindowsVisualStudioLanguageOptions - Set the default language options for Windows.
+static void GetWindowsVisualStudioLanguageOptions(LangOptions &Opts) {
+ Opts.Microsoft = true;
+}
+
+// x86-32 Windows Visual Studio target
+class VisualStudioWindowsX86_32TargetInfo : public WindowsX86_32TargetInfo {
+public:
+ VisualStudioWindowsX86_32TargetInfo(const std::string& triple)
+ : WindowsX86_32TargetInfo(triple) {
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ std::vector<char> &Defines) const {
+ WindowsX86_32TargetInfo::getTargetDefines(Opts, Defines);
+ // The value of the following reflects processor type.
+ // 300=386, 400=486, 500=Pentium, 600=Blend (default)
+ // We lost the original triple, so we use the default.
+ Define(Defines, "_M_IX86", "600");
+ }
virtual void getDefaultLangOptions(LangOptions &Opts) {
- X86_32TargetInfo::getDefaultLangOptions(Opts);
- GetWindowsLanguageOptions(Opts, getTargetTriple());
+ WindowsX86_32TargetInfo::getDefaultLangOptions(Opts);
+ GetWindowsVisualStudioLanguageOptions(Opts);
+ }
+};
+} // end anonymous namespace
+
+namespace {
+// x86-32 MinGW target
+class MinGWX86_32TargetInfo : public WindowsX86_32TargetInfo {
+public:
+ MinGWX86_32TargetInfo(const std::string& triple)
+ : WindowsX86_32TargetInfo(triple) {
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ std::vector<char> &Defines) const {
+ WindowsX86_32TargetInfo::getTargetDefines(Opts, Defines);
+ Define(Defines, "__MSVCRT__");
+ Define(Defines, "__MINGW32__");
+ Define(Defines, "__declspec", "__declspec");
+ }
+};
+} // end anonymous namespace
+
+namespace {
+// x86-32 Cygwin target
+class CygwinX86_32TargetInfo : public X86_32TargetInfo {
+public:
+ CygwinX86_32TargetInfo(const std::string& triple)
+ : X86_32TargetInfo(triple) {
+ TLSSupported = false;
+ WCharType = UnsignedShort;
+ WCharWidth = WCharAlign = 16;
+ DoubleAlign = LongLongAlign = 64;
+ DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-"
+ "a0:0:64-f80:32:32";
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ std::vector<char> &Defines) const {
+ X86_32TargetInfo::getTargetDefines(Opts, Defines);
+ Define(Defines, "__CYGWIN__");
+ Define(Defines, "__CYGWIN32__");
+ DefineStd(Defines, "unix", Opts);
}
};
} // end anonymous namespace
@@ -963,13 +1049,75 @@ public:
"} __va_list_tag;"
"typedef __va_list_tag __builtin_va_list[1];";
}
+
+ int getEHDataRegisterNumber(unsigned RegNo) const {
+ if (RegNo == 0) return 0;
+ if (RegNo == 1) return 1;
+ return -1;
+ }
+};
+} // end anonymous namespace
+
+namespace {
+// x86-64 Windows target
+class WindowsX86_64TargetInfo : public X86_64TargetInfo {
+public:
+ WindowsX86_64TargetInfo(const std::string& triple)
+ : X86_64TargetInfo(triple) {
+ TLSSupported = false;
+ WCharType = UnsignedShort;
+ WCharWidth = WCharAlign = 16;
+ LongWidth = LongAlign = 32;
+ DoubleAlign = LongLongAlign = 64;
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ std::vector<char> &Defines) const {
+ X86_64TargetInfo::getTargetDefines(Opts, Defines);
+ Define(Defines, "_WIN64");
+ DefineStd(Defines, "WIN64", Opts);
+ }
+};
+} // end anonymous namespace
+
+namespace {
+// x86-64 Windows Visual Studio target
+class VisualStudioWindowsX86_64TargetInfo : public WindowsX86_64TargetInfo {
+public:
+ VisualStudioWindowsX86_64TargetInfo(const std::string& triple)
+ : WindowsX86_64TargetInfo(triple) {
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ std::vector<char> &Defines) const {
+ WindowsX86_64TargetInfo::getTargetDefines(Opts, Defines);
+ Define(Defines, "_M_X64");
+ }
+ virtual const char *getVAListDeclaration() const {
+ return "typedef char* va_list;";
+ }
+};
+} // end anonymous namespace
+
+namespace {
+// x86-64 MinGW target
+class MinGWX86_64TargetInfo : public WindowsX86_64TargetInfo {
+public:
+ MinGWX86_64TargetInfo(const std::string& triple)
+ : WindowsX86_64TargetInfo(triple) {
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ std::vector<char> &Defines) const {
+ WindowsX86_64TargetInfo::getTargetDefines(Opts, Defines);
+ Define(Defines, "__MSVCRT__");
+ Define(Defines, "__MINGW64__");
+ Define(Defines, "__declspec");
+ }
};
} // end anonymous namespace
namespace {
class DarwinX86_64TargetInfo : public DarwinTargetInfo<X86_64TargetInfo> {
public:
- DarwinX86_64TargetInfo(const std::string& triple)
+ DarwinX86_64TargetInfo(const std::string& triple)
: DarwinTargetInfo<X86_64TargetInfo>(triple) {
Int64Type = SignedLongLong;
}
@@ -977,33 +1125,107 @@ public:
} // end anonymous namespace
namespace {
+class OpenBSDX86_64TargetInfo : public OpenBSDTargetInfo<X86_64TargetInfo> {
+public:
+ OpenBSDX86_64TargetInfo(const std::string& triple)
+ : OpenBSDTargetInfo<X86_64TargetInfo>(triple) {
+ IntMaxType = SignedLongLong;
+ UIntMaxType = UnsignedLongLong;
+ Int64Type = SignedLongLong;
+ }
+};
+} // end anonymous namespace
+
+namespace {
class ARMTargetInfo : public TargetInfo {
enum {
Armv4t,
Armv5,
Armv6,
+ Armv7a,
XScale
} ArmArch;
+
+ static const TargetInfo::GCCRegAlias GCCRegAliases[];
+ static const char * const GCCRegNames[];
+
+ std::string ABI;
+ bool IsThumb;
+
public:
- ARMTargetInfo(const std::string& triple) : TargetInfo(triple) {
- // FIXME: Are the defaults correct for ARM?
- DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
- "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:64";
- if (triple.find("arm-") == 0 || triple.find("armv6-") == 0)
+ ARMTargetInfo(const std::string &TripleStr)
+ : TargetInfo(TripleStr), ABI("aapcs-linux"), IsThumb(false)
+ {
+ llvm::Triple Triple(TripleStr);
+
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+
+ // FIXME: This shouldn't be done this way, we should use features to
+ // indicate the arch. See lib/Driver/Tools.cpp.
+ llvm::StringRef Version(""), Arch = Triple.getArchName();
+ if (Arch.startswith("arm"))
+ Version = Arch.substr(3);
+ else if (Arch.startswith("thumb"))
+ Version = Arch.substr(5);
+ if (Version == "v7")
+ ArmArch = Armv7a;
+ else if (Version.empty() || Version == "v6" || Version == "v6t2")
ArmArch = Armv6;
- else if (triple.find("armv5-") == 0)
+ else if (Version == "v5")
ArmArch = Armv5;
- else if (triple.find("armv4t-") == 0)
+ else if (Version == "v4t")
ArmArch = Armv4t;
- else if (triple.find("xscale-") == 0)
+ else if (Arch == "xscale" || Arch == "thumbv5e")
ArmArch = XScale;
- else if (triple.find("armv") == 0) {
- // FIXME: fuzzy match for other random weird arm triples. This is useful
- // for the static analyzer and other clients, but probably should be
- // re-evaluated when codegen is brought up.
+ else
ArmArch = Armv6;
+
+ if (Arch.startswith("thumb"))
+ IsThumb = true;
+
+ if (IsThumb) {
+ DescriptionString = ("e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-"
+ "v64:64:64-v128:128:128-a0:0:32");
+ } else {
+ DescriptionString = ("e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-"
+ "v64:64:64-v128:128:128-a0:0:64");
}
}
+ virtual const char *getABI() const { return ABI.c_str(); }
+ virtual bool setABI(const std::string &Name) {
+ ABI = Name;
+
+ // The defaults (above) are for AAPCS, check if we need to change them.
+ //
+ // FIXME: We need support for -meabi... we could just mangle it into the
+ // name.
+ if (Name == "apcs-gnu") {
+ DoubleAlign = LongLongAlign = 32;
+ SizeType = UnsignedLong;
+
+ if (IsThumb) {
+ DescriptionString = ("e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-"
+ "i64:32:32-f32:32:32-f64:32:32-"
+ "v64:64:64-v128:128:128-a0:0:32");
+ } else {
+ DescriptionString = ("e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:32:32-f32:32:32-f64:32:32-"
+ "v64:64:64-v128:128:128-a0:0:64");
+ }
+
+ // FIXME: Override "preferred align" for double and long long.
+ } else if (Name == "aapcs") {
+ // FIXME: Enumerated types are variable width in straight AAPCS.
+ } else if (Name == "aapcs-linux") {
+ ;
+ } else
+ return false;
+
+ return true;
+ }
virtual void getTargetDefines(const LangOptions &Opts,
std::vector<char> &Defs) const {
// Target identification.
@@ -1014,7 +1236,13 @@ public:
Define(Defs, "__LITTLE_ENDIAN__");
// Subtarget options.
- if (ArmArch == Armv6) {
+ //
+ // FIXME: Neither THUMB_INTERWORK nor SOFTFP is not being set correctly
+ // here.
+ if (ArmArch == Armv7a) {
+ Define(Defs, "__ARM_ARCH_7A__");
+ Define(Defs, "__THUMB_INTERWORK__");
+ } else if (ArmArch == Armv6) {
Define(Defs, "__ARM_ARCH_6K__");
Define(Defs, "__THUMB_INTERWORK__");
} else if (ArmArch == Armv5) {
@@ -1029,9 +1257,22 @@ public:
Define(Defs, "__XSCALE__");
Define(Defs, "__SOFTFP__");
}
+
Define(Defs, "__ARMEL__");
+
+ if (IsThumb) {
+ Define(Defs, "__THUMBEL__");
+ Define(Defs, "__thumb__");
+ if (ArmArch == Armv7a)
+ Define(Defs, "__thumb2__");
+ }
+
+ // Note, this is always on in gcc, even though it doesn't make sense.
Define(Defs, "__APCS_32__");
+ // FIXME: This should be conditional on VFP instruction support.
Define(Defs, "__VFP_FP__");
+
+ Define(Defs, "__USING_SJLJ_EXCEPTIONS__");
}
virtual void getTargetBuiltins(const Builtin::Info *&Records,
unsigned &NumRecords) const {
@@ -1042,21 +1283,10 @@ public:
virtual const char *getVAListDeclaration() const {
return "typedef char* __builtin_va_list;";
}
- virtual const char *getTargetPrefix() const {
- return "arm";
- }
virtual void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {
- // FIXME: Implement.
- Names = 0;
- NumNames = 0;
- }
+ unsigned &NumNames) const;
virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const {
- // FIXME: Implement.
- Aliases = 0;
- NumAliases = 0;
- }
+ unsigned &NumAliases) const;
virtual bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const {
// FIXME: Check if this is complete
@@ -1076,21 +1306,58 @@ public:
return "";
}
};
+
+const char * const ARMTargetInfo::GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+};
+
+void ARMTargetInfo::getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
+ Names = GCCRegNames;
+ NumNames = llvm::array_lengthof(GCCRegNames);
+}
+
+const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = {
+
+ { { "a1" }, "r0" },
+ { { "a2" }, "r1" },
+ { { "a3" }, "r2" },
+ { { "a4" }, "r3" },
+ { { "v1" }, "r4" },
+ { { "v2" }, "r5" },
+ { { "v3" }, "r6" },
+ { { "v4" }, "r7" },
+ { { "v5" }, "r8" },
+ { { "v6", "rfp" }, "r9" },
+ { { "sl" }, "r10" },
+ { { "fp" }, "r11" },
+ { { "ip" }, "r12" },
+ { { "sp" }, "r13" },
+ { { "lr" }, "r14" },
+ { { "pc" }, "r15" },
+};
+
+void ARMTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {
+ Aliases = GCCRegAliases;
+ NumAliases = llvm::array_lengthof(GCCRegAliases);
+}
} // end anonymous namespace.
namespace {
-class DarwinARMTargetInfo :
+class DarwinARMTargetInfo :
public DarwinTargetInfo<ARMTargetInfo> {
protected:
- virtual void getOSDefines(const LangOptions &Opts, const char *Triple,
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
std::vector<char> &Defines) const {
getDarwinDefines(Defines, Opts);
getDarwinIPhoneOSDefines(Defines, Triple);
}
public:
- DarwinARMTargetInfo(const std::string& triple)
+ DarwinARMTargetInfo(const std::string& triple)
: DarwinTargetInfo<ARMTargetInfo>(triple) {}
};
} // end anonymous namespace.
@@ -1118,9 +1385,6 @@ public:
virtual const char *getVAListDeclaration() const {
return "typedef void* __builtin_va_list;";
}
- virtual const char *getTargetPrefix() const {
- return "sparc";
- }
virtual void getGCCRegNames(const char * const *&Names,
unsigned &NumNames) const;
virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
@@ -1236,12 +1500,25 @@ namespace {
virtual void getTargetDefines(const LangOptions &Opts,
std::vector<char> &Defines) const {
Define(Defines, "__pic16");
+ Define(Defines, "rom", "__attribute__((address_space(1)))");
+ Define(Defines, "ram", "__attribute__((address_space(0)))");
+ Define(Defines, "_section(SectName)",
+ "__attribute__((section(SectName)))");
+ Define(Defines, "_address(Addr)",
+ "__attribute__((section(\"Address=\"#Addr)))");
+ Define(Defines, "_CONFIG(conf)", "asm(\"CONFIG \"#conf)");
+ Define(Defines, "_interrupt",
+ "__attribute__((section(\"interrupt=0x4\"))) \
+ __attribute__((used))");
}
virtual void getTargetBuiltins(const Builtin::Info *&Records,
unsigned &NumRecords) const {}
- virtual const char *getVAListDeclaration() const { return "";}
- virtual const char *getClobbers() const {return "";}
- virtual const char *getTargetPrefix() const {return "pic16";}
+ virtual const char *getVAListDeclaration() const {
+ return "";
+ }
+ virtual const char *getClobbers() const {
+ return "";
+ }
virtual void getGCCRegNames(const char * const *&Names,
unsigned &NumNames) const {}
virtual bool validateAsmConstraint(const char *&Name,
@@ -1286,9 +1563,6 @@ namespace {
Records = 0;
NumRecords = 0;
}
- virtual const char *getTargetPrefix() const {
- return "msp430";
- }
virtual void getGCCRegNames(const char * const *&Names,
unsigned &NumNames) const;
virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
@@ -1325,93 +1599,309 @@ namespace {
}
+namespace {
+ class SystemZTargetInfo : public TargetInfo {
+ static const char * const GCCRegNames[];
+ public:
+ SystemZTargetInfo(const std::string& triple) : TargetInfo(triple) {
+ TLSSupported = false;
+ IntWidth = IntAlign = 32;
+ LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64;
+ PointerWidth = PointerAlign = 64;
+ DescriptionString = "E-p:64:64:64-i8:8:16-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-a0:16:16";
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ std::vector<char> &Defines) const {
+ Define(Defines, "__s390__");
+ Define(Defines, "__s390x__");
+ }
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const {
+ // FIXME: Implement.
+ Records = 0;
+ NumRecords = 0;
+ }
+
+ virtual void getDefaultLangOptions(LangOptions &Opts) {
+ TargetInfo::getDefaultLangOptions(Opts);
+ Opts.CharIsSigned = false;
+ }
+
+ virtual void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const;
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {
+ // No aliases.
+ Aliases = 0;
+ NumAliases = 0;
+ }
+ virtual bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const {
+ // FIXME: implement
+ return true;
+ }
+ virtual const char *getClobbers() const {
+ // FIXME: Is this really right?
+ return "";
+ }
+ virtual const char *getVAListDeclaration() const {
+ // FIXME: implement
+ return "typedef char* __builtin_va_list;";
+ }
+ };
+
+ const char * const SystemZTargetInfo::GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+ };
+
+ void SystemZTargetInfo::getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
+ Names = GCCRegNames;
+ NumNames = llvm::array_lengthof(GCCRegNames);
+ }
+}
+
+namespace {
+ class BlackfinTargetInfo : public TargetInfo {
+ static const char * const GCCRegNames[];
+ public:
+ BlackfinTargetInfo(const std::string& triple) : TargetInfo(triple) {
+ TLSSupported = false;
+ DoubleAlign = 32;
+ LongLongAlign = 32;
+ LongDoubleAlign = 32;
+ DescriptionString = "e-p:32:32-i64:32-f64:32";
+ }
+
+ virtual void getTargetDefines(const LangOptions &Opts,
+ std::vector<char> &Defines) const {
+ DefineStd(Defines, "bfin", Opts);
+ DefineStd(Defines, "BFIN", Opts);
+ Define(Defines, "__ADSPBLACKFIN__");
+ // FIXME: This one is really dependent on -mcpu
+ Define(Defines, "__ADSPLPBLACKFIN__");
+ // FIXME: Add cpu-dependent defines and __SILICON_REVISION__
+ }
+
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const {
+ // FIXME: Implement.
+ Records = 0;
+ NumRecords = 0;
+ }
+
+ virtual void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const;
+
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {
+ // No aliases.
+ Aliases = 0;
+ NumAliases = 0;
+ }
+
+ virtual bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const {
+ if (strchr("adzDWeABbvfcCtukxywZY", Name[0])) {
+ Info.setAllowsRegister();
+ return true;
+ }
+ return false;
+ }
+
+ virtual const char *getClobbers() const {
+ return "";
+ }
+
+ virtual const char *getVAListDeclaration() const {
+ return "typedef char* __builtin_va_list;";
+ }
+ };
+
+ const char * const BlackfinTargetInfo::GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "p0", "p1", "p2", "p3", "p4", "p5", "sp", "fp",
+ "i0", "i1", "i2", "i3", "b0", "b1", "b2", "b3",
+ "l0", "l1", "l2", "l3", "m0", "m1", "m2", "m3",
+ "a0", "a1", "cc",
+ "rets", "reti", "retx", "retn", "rete", "astat", "seqstat", "usp",
+ "argp", "lt0", "lt1", "lc0", "lc1", "lb0", "lb1"
+ };
+
+ void BlackfinTargetInfo::getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
+ Names = GCCRegNames;
+ NumNames = llvm::array_lengthof(GCCRegNames);
+ }
+}
+
+namespace {
+
+ // LLVM and Clang cannot be used directly to output native binaries for
+ // target, but is used to compile C code to llvm bitcode with correct
+ // type and alignment information.
+ //
+ // TCE uses the llvm bitcode as input and uses it for generating customized
+ // target processor and program binary. TCE co-design environment is
+ // publicly available in http://tce.cs.tut.fi
+
+ class TCETargetInfo : public TargetInfo{
+ public:
+ TCETargetInfo(const std::string& triple) : TargetInfo(triple) {
+ TLSSupported = false;
+ IntWidth = 32;
+ LongWidth = LongLongWidth = 32;
+ IntMaxTWidth = 32;
+ PointerWidth = 32;
+ IntAlign = 32;
+ LongAlign = LongLongAlign = 32;
+ PointerAlign = 32;
+ SizeType = UnsignedInt;
+ IntMaxType = SignedLong;
+ UIntMaxType = UnsignedLong;
+ IntPtrType = SignedInt;
+ PtrDiffType = SignedInt;
+ FloatWidth = 32;
+ FloatAlign = 32;
+ DoubleWidth = 32;
+ DoubleAlign = 32;
+ LongDoubleWidth = 32;
+ LongDoubleAlign = 32;
+ FloatFormat = &llvm::APFloat::IEEEsingle;
+ DoubleFormat = &llvm::APFloat::IEEEsingle;
+ LongDoubleFormat = &llvm::APFloat::IEEEsingle;
+ DescriptionString = "E-p:32:32:32-a0:32:32"
+ "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64"
+ "-f32:32:32-f64:32:64";
+ }
+
+ virtual void getTargetDefines(const LangOptions &Opts,
+ std::vector<char> &Defines) const {
+ DefineStd(Defines, "tce", Opts);
+ Define(Defines, "__TCE__");
+ Define(Defines, "__TCE_V1__");
+ }
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const {}
+ virtual const char *getClobbers() const {
+ return "";
+ }
+ virtual const char *getVAListDeclaration() const {
+ return "typedef void* __builtin_va_list;";
+ }
+ virtual void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {}
+ virtual bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const {
+ return true;
+ }
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {}
+ };
+}
+
//===----------------------------------------------------------------------===//
// Driver code
//===----------------------------------------------------------------------===//
-static inline bool IsX86(const std::string& TT) {
- return (TT.size() >= 5 && TT[0] == 'i' && TT[2] == '8' && TT[3] == '6' &&
- TT[4] == '-' && TT[1] - '3' < 6);
-}
-
/// CreateTargetInfo - Return the target info object for the specified target
/// triple.
TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {
- // OS detection; this isn't really anywhere near complete.
- // Additions and corrections are welcome.
- bool isDarwin = T.find("-darwin") != std::string::npos;
- bool isDragonFly = T.find("-dragonfly") != std::string::npos;
- bool isOpenBSD = T.find("-openbsd") != std::string::npos;
- bool isFreeBSD = T.find("-freebsd") != std::string::npos;
- bool isSolaris = T.find("-solaris") != std::string::npos;
- bool isLinux = T.find("-linux") != std::string::npos;
- bool isWindows = T.find("-windows") != std::string::npos ||
- T.find("-win32") != std::string::npos ||
- T.find("-mingw") != std::string::npos;
-
- if (T.find("ppc-") == 0 || T.find("powerpc-") == 0) {
- if (isDarwin)
+ llvm::Triple Triple(T);
+ llvm::Triple::OSType os = Triple.getOS();
+
+ switch (Triple.getArch()) {
+ default:
+ return NULL;
+
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ switch (os) {
+ case llvm::Triple::Darwin:
+ return new DarwinARMTargetInfo(T);
+ case llvm::Triple::FreeBSD:
+ return new FreeBSDTargetInfo<ARMTargetInfo>(T);
+ default:
+ return new ARMTargetInfo(T);
+ }
+
+ case llvm::Triple::bfin:
+ return new BlackfinTargetInfo(T);
+
+ case llvm::Triple::msp430:
+ return new MSP430TargetInfo(T);
+
+ case llvm::Triple::pic16:
+ return new PIC16TargetInfo(T);
+
+ case llvm::Triple::ppc:
+ if (os == llvm::Triple::Darwin)
return new DarwinTargetInfo<PPCTargetInfo>(T);
return new PPC32TargetInfo(T);
- }
- if (T.find("ppc64-") == 0 || T.find("powerpc64-") == 0) {
- if (isDarwin)
+ case llvm::Triple::ppc64:
+ if (os == llvm::Triple::Darwin)
return new DarwinTargetInfo<PPC64TargetInfo>(T);
return new PPC64TargetInfo(T);
- }
-
- if (T.find("armv") == 0 || T.find("arm-") == 0 || T.find("xscale") == 0) {
- if (isDarwin)
- return new DarwinARMTargetInfo(T);
- if (isFreeBSD)
- return new FreeBSDTargetInfo<ARMTargetInfo>(T);
- return new ARMTargetInfo(T);
- }
- if (T.find("sparc-") == 0) {
- if (isSolaris)
+ case llvm::Triple::sparc:
+ if (os == llvm::Triple::Solaris)
return new SolarisSparcV8TargetInfo(T);
return new SparcV8TargetInfo(T);
- }
-
- if (T.find("x86_64-") == 0 || T.find("amd64-") == 0) {
- if (isDarwin)
- return new DarwinX86_64TargetInfo(T);
- if (isLinux)
- return new LinuxTargetInfo<X86_64TargetInfo>(T);
- if (isOpenBSD)
- return new OpenBSDTargetInfo<X86_64TargetInfo>(T);
- if (isFreeBSD)
- return new FreeBSDTargetInfo<X86_64TargetInfo>(T);
- if (isSolaris)
- return new SolarisTargetInfo<X86_64TargetInfo>(T);
- return new X86_64TargetInfo(T);
- }
- if (T.find("pic16-") == 0)
- return new PIC16TargetInfo(T);
+ case llvm::Triple::systemz:
+ return new SystemZTargetInfo(T);
- if (T.find("msp430-") == 0)
- return new MSP430TargetInfo(T);
+ case llvm::Triple::tce:
+ return new TCETargetInfo(T);
- if (IsX86(T)) {
- if (isDarwin)
+ case llvm::Triple::x86:
+ switch (os) {
+ case llvm::Triple::Darwin:
return new DarwinI386TargetInfo(T);
- if (isLinux)
+ case llvm::Triple::Linux:
return new LinuxTargetInfo<X86_32TargetInfo>(T);
- if (isDragonFly)
+ case llvm::Triple::DragonFly:
return new DragonFlyBSDTargetInfo<X86_32TargetInfo>(T);
- if (isOpenBSD)
- return new OpenBSDTargetInfo<X86_32TargetInfo>(T);
- if (isFreeBSD)
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<X86_32TargetInfo>(T);
+ case llvm::Triple::OpenBSD:
+ return new OpenBSDI386TargetInfo(T);
+ case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<X86_32TargetInfo>(T);
- if (isSolaris)
+ case llvm::Triple::Solaris:
return new SolarisTargetInfo<X86_32TargetInfo>(T);
- if (isWindows)
- return new WindowsX86_32TargetInfo(T);
- return new X86_32TargetInfo(T);
- }
+ case llvm::Triple::Cygwin:
+ return new CygwinX86_32TargetInfo(T);
+ case llvm::Triple::MinGW32:
+ return new MinGWX86_32TargetInfo(T);
+ case llvm::Triple::Win32:
+ return new VisualStudioWindowsX86_32TargetInfo(T);
+ default:
+ return new X86_32TargetInfo(T);
+ }
- return NULL;
+ case llvm::Triple::x86_64:
+ switch (os) {
+ case llvm::Triple::Darwin:
+ return new DarwinX86_64TargetInfo(T);
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<X86_64TargetInfo>(T);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<X86_64TargetInfo>(T);
+ case llvm::Triple::OpenBSD:
+ return new OpenBSDX86_64TargetInfo(T);
+ case llvm::Triple::FreeBSD:
+ return new FreeBSDTargetInfo<X86_64TargetInfo>(T);
+ case llvm::Triple::Solaris:
+ return new SolarisTargetInfo<X86_64TargetInfo>(T);
+ case llvm::Triple::MinGW64:
+ return new MinGWX86_64TargetInfo(T);
+ case llvm::Triple::Win32: // This is what Triple.h supports now.
+ return new VisualStudioWindowsX86_64TargetInfo(T);
+ default:
+ return new X86_64TargetInfo(T);
+ }
+ }
}
diff --git a/lib/Basic/Version.cpp b/lib/Basic/Version.cpp
new file mode 100644
index 0000000000000..30383f6251f64
--- /dev/null
+++ b/lib/Basic/Version.cpp
@@ -0,0 +1,49 @@
+//===- Version.cpp - Clang Version Number -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines several version-related utility functions for Clang.
+//
+//===----------------------------------------------------------------------===//
+#include <cstring>
+#include <cstdlib>
+using namespace std;
+
+namespace clang {
+
+const char *getClangSubversionPath() {
+ static const char *Path = 0;
+ if (Path)
+ return Path;
+
+ static char URL[] = "$URL: http://llvm.org/svn/llvm-project/cfe/trunk/lib/Basic/Version.cpp $";
+ char *End = strstr(URL, "/lib/Basic");
+ if (End)
+ *End = 0;
+
+ char *Begin = strstr(URL, "cfe/");
+ if (Begin) {
+ Path = Begin + 4;
+ return Path;
+ }
+
+ Path = URL;
+ return Path;
+}
+
+
+unsigned getClangSubversionRevision() {
+#ifndef SVN_REVISION
+ // Subversion was not available at build time?
+ return 0;
+#else
+ return strtol(SVN_REVISION, 0, 10);
+#endif
+}
+
+} // end namespace clang