summaryrefslogtreecommitdiffstats
path: root/lib/Basic
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Basic')
-rw-r--r--lib/Basic/CMakeLists.txt4
-rw-r--r--lib/Basic/Diagnostic.cpp23
-rw-r--r--lib/Basic/DiagnosticIDs.cpp144
-rw-r--r--lib/Basic/FileManager.cpp73
-rw-r--r--lib/Basic/IdentifierTable.cpp85
-rw-r--r--lib/Basic/SourceManager.cpp220
-rw-r--r--lib/Basic/TargetInfo.cpp12
-rw-r--r--lib/Basic/Targets.cpp227
-rw-r--r--lib/Basic/Version.cpp19
-rw-r--r--lib/Basic/VersionTuple.cpp36
10 files changed, 661 insertions, 182 deletions
diff --git a/lib/Basic/CMakeLists.txt b/lib/Basic/CMakeLists.txt
index 91e7deb..c1e7cf6 100644
--- a/lib/Basic/CMakeLists.txt
+++ b/lib/Basic/CMakeLists.txt
@@ -14,6 +14,7 @@ add_clang_library(clangBasic
Targets.cpp
TokenKinds.cpp
Version.cpp
+ VersionTuple.cpp
)
# Determine Subversion revision.
@@ -39,5 +40,6 @@ add_dependencies(clangBasic
ClangDiagnosticGroups
ClangDiagnosticLex
ClangDiagnosticParse
- ClangDiagnosticSema)
+ ClangDiagnosticSema
+ ClangDiagnosticIndexName)
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index 31e3331..e8cd218 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -16,6 +16,8 @@
#include "clang/Basic/PartialDiagnostic.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/CrashRecoveryContext.h"
+
using namespace clang;
static void DummyArgToStringFn(Diagnostic::ArgumentKind AK, intptr_t QT,
@@ -49,11 +51,6 @@ Diagnostic::Diagnostic(const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &diags,
ErrorLimit = 0;
TemplateBacktraceLimit = 0;
- // Create a DiagState and DiagStatePoint representing diagnostic changes
- // through command-line.
- DiagStates.push_back(DiagState());
- PushDiagStatePoint(&DiagStates.back(), SourceLocation());
-
Reset();
}
@@ -100,6 +97,16 @@ void Diagnostic::Reset() {
// displayed.
LastDiagLevel = (DiagnosticIDs::Level)-1;
DelayedDiagID = 0;
+
+ // Clear state related to #pragma diagnostic.
+ DiagStates.clear();
+ DiagStatePoints.clear();
+ DiagStateOnPushStack.clear();
+
+ // Create a DiagState and DiagStatePoint representing diagnostic changes
+ // through command-line.
+ DiagStates.push_back(DiagState());
+ PushDiagStatePoint(&DiagStates.back(), SourceLocation());
}
void Diagnostic::SetDelayedDiagnostic(unsigned DiagID, llvm::StringRef Arg1,
@@ -168,7 +175,7 @@ void Diagnostic::setDiagnosticMapping(diag::kind Diag, diag::Mapping Map,
// after the previous one.
if ((Loc.isValid() && LastStateChangePos.isInvalid()) ||
LastStateChangePos.isBeforeInTranslationUnitThan(Loc)) {
- // A diagnostic pragma occured, create a new DiagState initialized with
+ // A diagnostic pragma occurred, create a new DiagState initialized with
// the current one and a new DiagStatePoint to record at which location
// the new state became active.
DiagStates.push_back(*GetCurDiagState());
@@ -683,5 +690,7 @@ PartialDiagnostic::StorageAllocator::StorageAllocator() {
}
PartialDiagnostic::StorageAllocator::~StorageAllocator() {
- assert(NumFreeListEntries == NumCached && "A partial is on the lamb");
+ // Don't assert if we are in a CrashRecovery context, as this
+ // invariant may be invalidated during a crash.
+ assert((NumFreeListEntries == NumCached || llvm::CrashRecoveryContext::isRecoveringFromCrash()) && "A partial is on the lamb");
}
diff --git a/lib/Basic/DiagnosticIDs.cpp b/lib/Basic/DiagnosticIDs.cpp
index 553e4c9..b4dd575 100644
--- a/lib/Basic/DiagnosticIDs.cpp
+++ b/lib/Basic/DiagnosticIDs.cpp
@@ -46,19 +46,41 @@ struct StaticDiagInfoRec {
unsigned AccessControl : 1;
unsigned Category : 5;
+ const char *Name;
+
const char *Description;
const char *OptionGroup;
+ const char *BriefExplanation;
+ const char *FullExplanation;
+
bool operator<(const StaticDiagInfoRec &RHS) const {
return DiagID < RHS.DiagID;
}
};
+struct StaticDiagNameIndexRec {
+ const char *Name;
+ unsigned short DiagID;
+
+ bool operator<(const StaticDiagNameIndexRec &RHS) const {
+ assert(Name && RHS.Name && "Null Diagnostic Name");
+ return strcmp(Name, RHS.Name) == -1;
+ }
+
+ bool operator==(const StaticDiagNameIndexRec &RHS) const {
+ assert(Name && RHS.Name && "Null Diagnostic Name");
+ return strcmp(Name, RHS.Name) == 0;
+ }
+};
+
}
static const StaticDiagInfoRec StaticDiagInfo[] = {
-#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) \
- { diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, ACCESS, CATEGORY, DESC, GROUP },
+#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP, \
+ SFINAE,ACCESS,CATEGORY,BRIEF,FULL) \
+ { diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, \
+ ACCESS, CATEGORY, #ENUM, DESC, GROUP, BRIEF, FULL },
#include "clang/Basic/DiagnosticCommonKinds.inc"
#include "clang/Basic/DiagnosticDriverKinds.inc"
#include "clang/Basic/DiagnosticFrontendKinds.inc"
@@ -67,20 +89,32 @@ static const StaticDiagInfoRec StaticDiagInfo[] = {
#include "clang/Basic/DiagnosticASTKinds.inc"
#include "clang/Basic/DiagnosticSemaKinds.inc"
#include "clang/Basic/DiagnosticAnalysisKinds.inc"
- { 0, 0, 0, 0, 0, 0, 0, 0}
-};
#undef DIAG
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+};
+
+static const unsigned StaticDiagInfoSize =
+ sizeof(StaticDiagInfo)/sizeof(StaticDiagInfo[0])-1;
+
+/// To be sorted before first use (since it's splitted among multiple files)
+static StaticDiagNameIndexRec StaticDiagNameIndex[] = {
+#define DIAG_NAME_INDEX(ENUM) { #ENUM, diag::ENUM },
+#include "clang/Basic/DiagnosticIndexName.inc"
+#undef DIAG_NAME_INDEX
+ { 0, 0 }
+};
+
+static const unsigned StaticDiagNameIndexSize =
+ sizeof(StaticDiagNameIndex)/sizeof(StaticDiagNameIndex[0])-1;
/// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID,
/// or null if the ID is invalid.
static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
- unsigned NumDiagEntries = sizeof(StaticDiagInfo)/sizeof(StaticDiagInfo[0])-1;
-
// If assertions are enabled, verify that the StaticDiagInfo array is sorted.
#ifndef NDEBUG
static bool IsFirst = true;
if (IsFirst) {
- for (unsigned i = 1; i != NumDiagEntries; ++i) {
+ for (unsigned i = 1; i != StaticDiagInfoSize; ++i) {
assert(StaticDiagInfo[i-1].DiagID != StaticDiagInfo[i].DiagID &&
"Diag ID conflict, the enums at the start of clang::diag (in "
"DiagnosticIDs.h) probably need to be increased");
@@ -93,11 +127,11 @@ static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
#endif
// Search the diagnostic table with a binary search.
- StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0, 0, 0, 0 };
+ StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
const StaticDiagInfoRec *Found =
- std::lower_bound(StaticDiagInfo, StaticDiagInfo + NumDiagEntries, Find);
- if (Found == StaticDiagInfo + NumDiagEntries ||
+ std::lower_bound(StaticDiagInfo, StaticDiagInfo + StaticDiagInfoSize, Find);
+ if (Found == StaticDiagInfo + StaticDiagInfoSize ||
Found->DiagID != DiagID)
return 0;
@@ -119,7 +153,7 @@ const char *DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) {
return 0;
}
-/// getWarningOptionForDiag - Return the category number that a specified
+/// getCategoryNumberForDiag - Return the category number that a specified
/// DiagID belongs to, or 0 if no category.
unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
@@ -167,7 +201,48 @@ DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) {
return SFINAE_Report;
}
-/// getDiagClass - Return the class field of the diagnostic.
+/// getName - Given a diagnostic ID, return its name
+const char *DiagnosticIDs::getName(unsigned DiagID) {
+ if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+ return Info->Name;
+ return 0;
+}
+
+/// getIdFromName - Given a diagnostic name, return its ID, or 0
+unsigned DiagnosticIDs::getIdFromName(char const *Name) {
+ StaticDiagNameIndexRec *StaticDiagNameIndexEnd =
+ StaticDiagNameIndex + StaticDiagNameIndexSize;
+
+ if (Name == 0) { return diag::DIAG_UPPER_LIMIT; }
+
+ StaticDiagNameIndexRec Find = { Name, 0 };
+
+ const StaticDiagNameIndexRec *Found =
+ std::lower_bound( StaticDiagNameIndex, StaticDiagNameIndexEnd, Find);
+ if (Found == StaticDiagNameIndexEnd ||
+ strcmp(Found->Name, Name) != 0)
+ return diag::DIAG_UPPER_LIMIT;
+
+ return Found->DiagID;
+}
+
+/// getBriefExplanation - Given a diagnostic ID, return a brief explanation
+/// of the issue
+const char *DiagnosticIDs::getBriefExplanation(unsigned DiagID) {
+ if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+ return Info->BriefExplanation;
+ return 0;
+}
+
+/// getFullExplanation - Given a diagnostic ID, return a full explanation
+/// of the issue
+const char *DiagnosticIDs::getFullExplanation(unsigned DiagID) {
+ if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+ return Info->FullExplanation;
+ return 0;
+}
+
+/// getBuiltinDiagClass - Return the class field of the diagnostic.
///
static unsigned getBuiltinDiagClass(unsigned DiagID) {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
@@ -329,6 +404,8 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
if (mapping)
*mapping = (diag::Mapping) (MappingInfo & 7);
+ bool ShouldEmitInSystemHeader = false;
+
switch (MappingInfo & 7) {
default: assert(0 && "Unknown mapping!");
case diag::MAP_IGNORE:
@@ -351,6 +428,9 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
case diag::MAP_FATAL:
Result = DiagnosticIDs::Fatal;
break;
+ case diag::MAP_WARNING_SHOW_IN_SYSTEM_HEADER:
+ ShouldEmitInSystemHeader = true;
+ // continue as MAP_WARNING.
case diag::MAP_WARNING:
// If warnings are globally mapped to ignore or error, do it.
if (Diag.IgnoreAllWarnings)
@@ -395,6 +475,20 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
if (Diag.AllExtensionsSilenced && isBuiltinExtensionDiag(DiagID))
return DiagnosticIDs::Ignored;
+ // If we are in a system header, we ignore it.
+ // We also want to ignore extensions and warnings in -Werror and
+ // -pedantic-errors modes, which *map* warnings/extensions to errors.
+ if (Result >= DiagnosticIDs::Warning &&
+ DiagClass != CLASS_ERROR &&
+ // Custom diagnostics always are emitted in system headers.
+ DiagID < diag::DIAG_UPPER_LIMIT &&
+ !ShouldEmitInSystemHeader &&
+ Diag.SuppressSystemWarnings &&
+ Loc.isValid() &&
+ Diag.getSourceManager().isInSystemHeader(
+ Diag.getSourceManager().getInstantiationLoc(Loc)))
+ return DiagnosticIDs::Ignored;
+
return Result;
}
@@ -480,16 +574,9 @@ bool DiagnosticIDs::ProcessDiag(Diagnostic &Diag) const {
DiagnosticIDs::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 {
// Get the class of the diagnostic. If this is a NOTE, map it onto whatever
// the diagnostic level was for the previous diagnostic so that it is
@@ -497,14 +584,7 @@ bool DiagnosticIDs::ProcessDiag(Diagnostic &Diag) const {
unsigned DiagClass = getBuiltinDiagClass(DiagID);
if (DiagClass == CLASS_NOTE) {
DiagLevel = DiagnosticIDs::Note;
- ShouldEmitInSystemHeader = false; // extra consideration is needed
} else {
- // 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, Info.getLocation(),
Diag);
}
@@ -540,18 +620,6 @@ bool DiagnosticIDs::ProcessDiag(Diagnostic &Diag) const {
Diag.LastDiagLevel == DiagnosticIDs::Ignored))
return false;
- // If this diagnostic is in a system header and is not a clang error, suppress
- // it.
- if (Diag.SuppressSystemWarnings && !ShouldEmitInSystemHeader &&
- Info.getLocation().isValid() &&
- Diag.getSourceManager().isInSystemHeader(
- Diag.getSourceManager().getInstantiationLoc(Info.getLocation())) &&
- (DiagLevel != DiagnosticIDs::Note ||
- Diag.LastDiagLevel == DiagnosticIDs::Ignored)) {
- Diag.LastDiagLevel = DiagnosticIDs::Ignored;
- return false;
- }
-
if (DiagLevel >= DiagnosticIDs::Error) {
if (Diag.Client->IncludeInDiagnosticCounts()) {
Diag.ErrorOccurred = true;
diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp
index 342413d..4e5a129 100644
--- a/lib/Basic/FileManager.cpp
+++ b/lib/Basic/FileManager.cpp
@@ -313,7 +313,7 @@ const DirectoryEntry *FileManager::getDirectory(llvm::StringRef DirName) {
/// getFile - Lookup, cache, and verify the specified file (real or
/// virtual). This returns NULL if the file doesn't exist.
///
-const FileEntry *FileManager::getFile(llvm::StringRef Filename) {
+const FileEntry *FileManager::getFile(llvm::StringRef Filename, bool openFile) {
++NumFileLookups;
// See if there is already an entry in the map.
@@ -354,6 +354,11 @@ const FileEntry *FileManager::getFile(llvm::StringRef Filename) {
return 0;
}
+ if (FileDescriptor != -1 && !openFile) {
+ close(FileDescriptor);
+ FileDescriptor = -1;
+ }
+
// 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 = UniqueRealFiles.getFile(InterndFileName, StatBuf);
@@ -450,13 +455,15 @@ FileManager::getVirtualFile(llvm::StringRef Filename, off_t Size,
return UFE;
}
-void FileManager::FixupRelativePath(llvm::sys::Path &path,
- const FileSystemOptions &FSOpts) {
- if (FSOpts.WorkingDir.empty() || llvm::sys::path::is_absolute(path.str()))
+void FileManager::FixupRelativePath(llvm::SmallVectorImpl<char> &path) const {
+ llvm::StringRef pathRef(path.data(), path.size());
+
+ if (FileSystemOpts.WorkingDir.empty()
+ || llvm::sys::path::is_absolute(pathRef))
return;
- llvm::SmallString<128> NewPath(FSOpts.WorkingDir);
- llvm::sys::path::append(NewPath, path.str());
+ llvm::SmallString<128> NewPath(FileSystemOpts.WorkingDir);
+ llvm::sys::path::append(NewPath, pathRef);
path = NewPath;
}
@@ -464,30 +471,32 @@ llvm::MemoryBuffer *FileManager::
getBufferForFile(const FileEntry *Entry, std::string *ErrorStr) {
llvm::OwningPtr<llvm::MemoryBuffer> Result;
llvm::error_code ec;
- if (FileSystemOpts.WorkingDir.empty()) {
- const char *Filename = Entry->getName();
- // If the file is already open, use the open file descriptor.
- if (Entry->FD != -1) {
- ec = llvm::MemoryBuffer::getOpenFile(Entry->FD, Filename, Result,
- Entry->getSize());
- if (ErrorStr)
- *ErrorStr = ec.message();
-
- close(Entry->FD);
- Entry->FD = -1;
- return Result.take();
- }
- // Otherwise, open the file.
+ const char *Filename = Entry->getName();
+ // If the file is already open, use the open file descriptor.
+ if (Entry->FD != -1) {
+ ec = llvm::MemoryBuffer::getOpenFile(Entry->FD, Filename, Result,
+ Entry->getSize());
+ if (ErrorStr)
+ *ErrorStr = ec.message();
+
+ close(Entry->FD);
+ Entry->FD = -1;
+ return Result.take();
+ }
+
+ // Otherwise, open the file.
+
+ if (FileSystemOpts.WorkingDir.empty()) {
ec = llvm::MemoryBuffer::getFile(Filename, Result, Entry->getSize());
if (ec && ErrorStr)
*ErrorStr = ec.message();
return Result.take();
}
-
- llvm::sys::Path FilePath(Entry->getName());
- FixupRelativePath(FilePath, FileSystemOpts);
- ec = llvm::MemoryBuffer::getFile(FilePath.c_str(), Result, Entry->getSize());
+
+ llvm::SmallString<128> FilePath(Entry->getName());
+ FixupRelativePath(FilePath);
+ ec = llvm::MemoryBuffer::getFile(FilePath.str(), Result, Entry->getSize());
if (ec && ErrorStr)
*ErrorStr = ec.message();
return Result.take();
@@ -504,8 +513,8 @@ getBufferForFile(llvm::StringRef Filename, std::string *ErrorStr) {
return Result.take();
}
- llvm::sys::Path FilePath(Filename);
- FixupRelativePath(FilePath, FileSystemOpts);
+ llvm::SmallString<128> FilePath(Filename);
+ FixupRelativePath(FilePath);
ec = llvm::MemoryBuffer::getFile(FilePath.c_str(), Result);
if (ec && ErrorStr)
*ErrorStr = ec.message();
@@ -525,13 +534,21 @@ bool FileManager::getStatValue(const char *Path, struct stat &StatBuf,
return FileSystemStatCache::get(Path, StatBuf, FileDescriptor,
StatCache.get());
- llvm::sys::Path FilePath(Path);
- FixupRelativePath(FilePath, FileSystemOpts);
+ llvm::SmallString<128> FilePath(Path);
+ FixupRelativePath(FilePath);
return FileSystemStatCache::get(FilePath.c_str(), StatBuf, FileDescriptor,
StatCache.get());
}
+bool FileManager::getNoncachedStatValue(llvm::StringRef Path,
+ struct stat &StatBuf) {
+ llvm::SmallString<128> FilePath(Path);
+ FixupRelativePath(FilePath);
+
+ return ::stat(FilePath.c_str(), &StatBuf) != 0;
+}
+
void FileManager::GetUniqueIDMapping(
llvm::SmallVectorImpl<const FileEntry *> &UIDToFiles) const {
UIDToFiles.clear();
diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp
index ef11d65..cb1f55b 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/lib/Basic/IdentifierTable.cpp
@@ -81,17 +81,18 @@ IdentifierTable::IdentifierTable(const LangOptions &LangOpts,
// Constants for TokenKinds.def
namespace {
enum {
- KEYALL = 1,
- KEYC99 = 2,
- KEYCXX = 4,
- KEYCXX0X = 8,
- KEYGNU = 16,
- KEYMS = 32,
- BOOLSUPPORT = 64,
- KEYALTIVEC = 128,
- KEYNOCXX = 256,
- KEYBORLAND = 512,
- KEYOPENCL = 1024
+ KEYC99 = 0x1,
+ KEYCXX = 0x2,
+ KEYCXX0X = 0x4,
+ KEYGNU = 0x8,
+ KEYMS = 0x10,
+ BOOLSUPPORT = 0x20,
+ KEYALTIVEC = 0x40,
+ KEYNOCXX = 0x80,
+ KEYBORLAND = 0x100,
+ KEYOPENCL = 0x200,
+ KEYC1X = 0x400,
+ KEYALL = 0x7ff
};
}
@@ -107,7 +108,7 @@ static void AddKeyword(llvm::StringRef Keyword,
tok::TokenKind TokenCode, unsigned Flags,
const LangOptions &LangOpts, IdentifierTable &Table) {
unsigned AddResult = 0;
- if (Flags & KEYALL) AddResult = 2;
+ if (Flags == KEYALL) AddResult = 2;
else if (LangOpts.CPlusPlus && (Flags & KEYCXX)) AddResult = 2;
else if (LangOpts.CPlusPlus0x && (Flags & KEYCXX0X)) AddResult = 2;
else if (LangOpts.C99 && (Flags & KEYC99)) AddResult = 2;
@@ -118,6 +119,7 @@ static void AddKeyword(llvm::StringRef Keyword,
else if (LangOpts.AltiVec && (Flags & KEYALTIVEC)) AddResult = 2;
else if (LangOpts.OpenCL && (Flags & KEYOPENCL)) AddResult = 2;
else if (!LangOpts.CPlusPlus && (Flags & KEYNOCXX)) AddResult = 2;
+ else if (LangOpts.C1X && (Flags & KEYC1X)) AddResult = 2;
// Don't add this keyword if disabled in this language.
if (AddResult == 0) return;
@@ -162,7 +164,12 @@ void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
#define OBJC2_AT_KEYWORD(NAME) \
if (LangOpts.ObjC2) \
AddObjCKeyword(llvm::StringRef(#NAME), tok::objc_##NAME, *this);
+#define TESTING_KEYWORD(NAME, FLAGS)
#include "clang/Basic/TokenKinds.def"
+
+ if (LangOpts.ParseUnknownAnytype)
+ AddKeyword("__unknown_anytype", tok::kw___unknown_anytype, KEYALL,
+ LangOpts, *this);
}
tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
@@ -364,6 +371,56 @@ std::string Selector::getAsString() const {
return reinterpret_cast<MultiKeywordSelector *>(InfoPtr)->getName();
}
+/// Interpreting the given string using the normal CamelCase
+/// conventions, determine whether the given string starts with the
+/// given "word", which is assumed to end in a lowercase letter.
+static bool startsWithWord(llvm::StringRef name, llvm::StringRef word) {
+ if (name.size() < word.size()) return false;
+ return ((name.size() == word.size() ||
+ !islower(name[word.size()]))
+ && name.startswith(word));
+}
+
+ObjCMethodFamily Selector::getMethodFamilyImpl(Selector sel) {
+ IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
+ if (!first) return OMF_None;
+
+ llvm::StringRef name = first->getName();
+ if (sel.isUnarySelector()) {
+ if (name == "autorelease") return OMF_autorelease;
+ if (name == "dealloc") return OMF_dealloc;
+ if (name == "release") return OMF_release;
+ if (name == "retain") return OMF_retain;
+ if (name == "retainCount") return OMF_retainCount;
+ }
+
+ // The other method families may begin with a prefix of underscores.
+ while (!name.empty() && name.front() == '_')
+ name = name.substr(1);
+
+ if (name.empty()) return OMF_None;
+ switch (name.front()) {
+ case 'a':
+ if (startsWithWord(name, "alloc")) return OMF_alloc;
+ break;
+ case 'c':
+ if (startsWithWord(name, "copy")) return OMF_copy;
+ break;
+ case 'i':
+ if (startsWithWord(name, "init")) return OMF_init;
+ break;
+ case 'm':
+ if (startsWithWord(name, "mutableCopy")) return OMF_mutableCopy;
+ break;
+ case 'n':
+ if (startsWithWord(name, "new")) return OMF_new;
+ break;
+ default:
+ break;
+ }
+
+ return OMF_None;
+}
namespace {
struct SelectorTableImpl {
@@ -376,6 +433,10 @@ static SelectorTableImpl &getSelectorTableImpl(void *P) {
return *static_cast<SelectorTableImpl*>(P);
}
+size_t SelectorTable::getTotalMemory() const {
+ SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl);
+ return SelTabImpl.Allocator.getTotalMemory();
+}
Selector SelectorTable::getSelector(unsigned nKeys, IdentifierInfo **IIV) {
if (nKeys < 2)
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index e2783ba..c3e0393 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -46,13 +46,26 @@ unsigned ContentCache::getSizeBytesMapped() const {
return Buffer.getPointer() ? Buffer.getPointer()->getBufferSize() : 0;
}
+/// Returns the kind of memory used to back the memory buffer for
+/// this content cache. This is used for performance analysis.
+llvm::MemoryBuffer::BufferKind ContentCache::getMemoryBufferKind() const {
+ assert(Buffer.getPointer());
+
+ // Should be unreachable, but keep for sanity.
+ if (!Buffer.getPointer())
+ return llvm::MemoryBuffer::MemoryBuffer_Malloc;
+
+ const llvm::MemoryBuffer *buf = Buffer.getPointer();
+ return buf->getBufferKind();
+}
+
/// 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.
unsigned ContentCache::getSize() const {
return Buffer.getPointer() ? (unsigned) Buffer.getPointer()->getBufferSize()
- : (unsigned) Entry->getSize();
+ : (unsigned) ContentsEntry->getSize();
}
void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B,
@@ -70,8 +83,8 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
SourceLocation Loc,
bool *Invalid) const {
// Lazily create the Buffer for ContentCaches that wrap files. If we already
- // computed it, jsut return what we have.
- if (Buffer.getPointer() || Entry == 0) {
+ // computed it, just return what we have.
+ if (Buffer.getPointer() || ContentsEntry == 0) {
if (Invalid)
*Invalid = isBufferInvalid();
@@ -79,7 +92,7 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
}
std::string ErrorStr;
- Buffer.setPointer(SM.getFileManager().getBufferForFile(Entry, &ErrorStr));
+ Buffer.setPointer(SM.getFileManager().getBufferForFile(ContentsEntry, &ErrorStr));
// If we were unable to open the file, then we are in an inconsistent
// situation where the content cache referenced a file which no longer
@@ -93,18 +106,18 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
// possible.
if (!Buffer.getPointer()) {
const llvm::StringRef FillStr("<<<MISSING SOURCE FILE>>>\n");
- Buffer.setPointer(MemoryBuffer::getNewMemBuffer(Entry->getSize(),
+ Buffer.setPointer(MemoryBuffer::getNewMemBuffer(ContentsEntry->getSize(),
"<invalid>"));
char *Ptr = const_cast<char*>(Buffer.getPointer()->getBufferStart());
- for (unsigned i = 0, e = Entry->getSize(); i != e; ++i)
+ for (unsigned i = 0, e = ContentsEntry->getSize(); i != e; ++i)
Ptr[i] = FillStr[i % FillStr.size()];
if (Diag.isDiagnosticInFlight())
Diag.SetDelayedDiagnostic(diag::err_cannot_open_file,
- Entry->getName(), ErrorStr);
+ ContentsEntry->getName(), ErrorStr);
else
Diag.Report(Loc, diag::err_cannot_open_file)
- << Entry->getName() << ErrorStr;
+ << ContentsEntry->getName() << ErrorStr;
Buffer.setInt(Buffer.getInt() | InvalidFlag);
@@ -114,25 +127,24 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
// Check that the file's size is the same as in the file entry (which may
// have come from a stat cache).
- if (getRawBuffer()->getBufferSize() != (size_t)Entry->getSize()) {
+ if (getRawBuffer()->getBufferSize() != (size_t)ContentsEntry->getSize()) {
if (Diag.isDiagnosticInFlight())
Diag.SetDelayedDiagnostic(diag::err_file_modified,
- Entry->getName());
+ ContentsEntry->getName());
else
Diag.Report(Loc, diag::err_file_modified)
- << Entry->getName();
+ << ContentsEntry->getName();
Buffer.setInt(Buffer.getInt() | InvalidFlag);
if (Invalid) *Invalid = true;
return Buffer.getPointer();
}
-
+
// If the buffer is valid, check to see if it has a UTF Byte Order Mark
- // (BOM). We only support UTF-8 without a BOM right now. See
+ // (BOM). We only support UTF-8 with and without a BOM right now. See
// http://en.wikipedia.org/wiki/Byte_order_mark for more information.
llvm::StringRef BufStr = Buffer.getPointer()->getBuffer();
- const char *BOM = llvm::StringSwitch<const char *>(BufStr)
- .StartsWith("\xEF\xBB\xBF", "UTF-8")
+ const char *InvalidBOM = llvm::StringSwitch<const char *>(BufStr)
.StartsWith("\xFE\xFF", "UTF-16 (BE)")
.StartsWith("\xFF\xFE", "UTF-16 (LE)")
.StartsWith("\x00\x00\xFE\xFF", "UTF-32 (BE)")
@@ -145,9 +157,9 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
.StartsWith("\x84\x31\x95\x33", "GB-18030")
.Default(0);
- if (BOM) {
+ if (InvalidBOM) {
Diag.Report(Loc, diag::err_unsupported_bom)
- << BOM << Entry->getName();
+ << InvalidBOM << ContentsEntry->getName();
Buffer.setInt(Buffer.getInt() | InvalidFlag);
}
@@ -279,7 +291,12 @@ void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo,
int FilenameID) {
std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc);
- const SrcMgr::FileInfo &FileInfo = getSLocEntry(LocInfo.first).getFile();
+ bool Invalid = false;
+ const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);
+ if (!Entry.isFile() || Invalid)
+ return;
+
+ const SrcMgr::FileInfo &FileInfo = Entry.getFile();
// Remember that this file has #line directives now if it doesn't already.
const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives();
@@ -303,7 +320,13 @@ void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo,
}
std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc);
- const SrcMgr::FileInfo &FileInfo = getSLocEntry(LocInfo.first).getFile();
+
+ bool Invalid = false;
+ const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);
+ if (!Entry.isFile() || Invalid)
+ return;
+
+ const SrcMgr::FileInfo &FileInfo = Entry.getFile();
// Remember that this file has #line directives now if it doesn't already.
const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives();
@@ -340,9 +363,9 @@ LineTableInfo &SourceManager::getLineTable() {
//===----------------------------------------------------------------------===//
SourceManager::SourceManager(Diagnostic &Diag, FileManager &FileMgr)
- : Diag(Diag), FileMgr(FileMgr),
+ : Diag(Diag), FileMgr(FileMgr), OverridenFilesKeepOriginalName(true),
ExternalSLocEntries(0), LineTable(0), NumLinearScans(0),
- NumBinaryProbes(0) {
+ NumBinaryProbes(0), FakeBufferForRecovery(0) {
clearIDTables();
Diag.setSourceManager(this);
}
@@ -362,6 +385,8 @@ SourceManager::~SourceManager() {
I->second->~ContentCache();
ContentCacheAlloc.Deallocate(I->second);
}
+
+ delete FakeBufferForRecovery;
}
void SourceManager::clearIDTables() {
@@ -395,7 +420,18 @@ SourceManager::getOrCreateContentCache(const FileEntry *FileEnt) {
unsigned EntryAlign = llvm::AlignOf<ContentCache>::Alignment;
EntryAlign = std::max(8U, EntryAlign);
Entry = ContentCacheAlloc.Allocate<ContentCache>(1, EntryAlign);
- new (Entry) ContentCache(FileEnt);
+
+ // If the file contents are overridden with contents from another file,
+ // pass that file to ContentCache.
+ llvm::DenseMap<const FileEntry *, const FileEntry *>::iterator
+ overI = OverriddenFiles.find(FileEnt);
+ if (overI == OverriddenFiles.end())
+ new (Entry) ContentCache(FileEnt);
+ else
+ new (Entry) ContentCache(OverridenFilesKeepOriginalName ? FileEnt
+ : overI->second,
+ overI->second);
+
return Entry;
}
@@ -445,6 +481,15 @@ void SourceManager::ClearPreallocatedSLocEntries() {
ExternalSLocEntries = 0;
}
+/// \brief As part of recovering from missing or changed content, produce a
+/// fake, non-empty buffer.
+const llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const {
+ if (!FakeBufferForRecovery)
+ FakeBufferForRecovery
+ = llvm::MemoryBuffer::getMemBuffer("<<<INVALID BUFFER>>");
+
+ return FakeBufferForRecovery;
+}
//===----------------------------------------------------------------------===//
// Methods to create new FileID's and instantiations.
@@ -531,10 +576,21 @@ void SourceManager::overrideFileContents(const FileEntry *SourceFile,
const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(Buffer, DoNotFree);
}
+void SourceManager::overrideFileContents(const FileEntry *SourceFile,
+ const FileEntry *NewFile) {
+ assert(SourceFile->getSize() == NewFile->getSize() &&
+ "Different sizes, use the FileManager to create a virtual file with "
+ "the correct size");
+ assert(FileInfos.count(SourceFile) == 0 &&
+ "This function should be called at the initialization stage, before "
+ "any parsing occurs.");
+ OverriddenFiles[SourceFile] = NewFile;
+}
+
llvm::StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
bool MyInvalid = false;
- const SLocEntry &SLoc = getSLocEntry(FID.ID);
- if (!SLoc.isFile()) {
+ const SLocEntry &SLoc = getSLocEntry(FID.ID, &MyInvalid);
+ if (!SLoc.isFile() || MyInvalid) {
if (Invalid)
*Invalid = true;
return "<<<<<INVALID SOURCE LOCATION>>>>>";
@@ -562,7 +618,8 @@ llvm::StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
/// SLocEntryTable which contains the specified location.
///
FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const {
- assert(SLocOffset && "Invalid FileID");
+ if (!SLocOffset)
+ return FileID::get(0);
// 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
@@ -590,8 +647,13 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const {
unsigned NumProbes = 0;
while (1) {
--I;
- if (ExternalSLocEntries)
- getSLocEntry(FileID::get(I - SLocEntryTable.begin()));
+ if (ExternalSLocEntries) {
+ bool Invalid = false;
+ getSLocEntry(FileID::get(I - SLocEntryTable.begin()), &Invalid);
+ if (Invalid)
+ return FileID::get(0);
+ }
+
if (I->getOffset() <= SLocOffset) {
#if 0
printf("lin %d -> %d [%s] %d %d\n", SLocOffset,
@@ -621,9 +683,13 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const {
unsigned LessIndex = 0;
NumProbes = 0;
while (1) {
+ bool Invalid = false;
unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex;
- unsigned MidOffset = getSLocEntry(FileID::get(MiddleIndex)).getOffset();
-
+ unsigned MidOffset = getSLocEntry(FileID::get(MiddleIndex), &Invalid)
+ .getOffset();
+ if (Invalid)
+ return FileID::get(0);
+
++NumProbes;
// If the offset of the midpoint is too large, chop the high side of the
@@ -773,9 +839,16 @@ const char *SourceManager::getCharacterData(SourceLocation SL,
// Note that calling 'getBuffer()' may lazily page in a source file.
bool CharDataInvalid = false;
+ const SLocEntry &Entry = getSLocEntry(LocInfo.first, &CharDataInvalid);
+ if (CharDataInvalid || !Entry.isFile()) {
+ if (Invalid)
+ *Invalid = true;
+
+ return "<<<<INVALID BUFFER>>>>";
+ }
const llvm::MemoryBuffer *Buffer
- = getSLocEntry(LocInfo.first).getFile().getContentCache()
- ->getBuffer(Diag, *this, SourceLocation(), &CharDataInvalid);
+ = Entry.getFile().getContentCache()
+ ->getBuffer(Diag, *this, SourceLocation(), &CharDataInvalid);
if (Invalid)
*Invalid = CharDataInvalid;
return Buffer->getBufferStart() + (CharDataInvalid? 0 : LocInfo.second);
@@ -891,10 +964,18 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos,
ContentCache *Content;
if (LastLineNoFileIDQuery == FID)
Content = LastLineNoContentCache;
- else
- Content = const_cast<ContentCache*>(getSLocEntry(FID)
- .getFile().getContentCache());
-
+ else {
+ bool MyInvalid = false;
+ const SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
+ if (MyInvalid || !Entry.isFile()) {
+ if (Invalid)
+ *Invalid = true;
+ return 1;
+ }
+
+ Content = const_cast<ContentCache*>(Entry.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) {
@@ -1021,7 +1102,12 @@ 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);
- const SrcMgr::FileInfo &FI = getSLocEntry(LocInfo.first).getFile();
+ bool Invalid = false;
+ const SLocEntry &SEntry = getSLocEntry(LocInfo.first, &Invalid);
+ if (Invalid || !SEntry.isFile())
+ return C_User;
+
+ const SrcMgr::FileInfo &FI = SEntry.getFile();
// If there are no #line directives in this file, just return the whole-file
// state.
@@ -1064,18 +1150,23 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const {
// Presumed locations are always for instantiation points.
std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc);
- const SrcMgr::FileInfo &FI = getSLocEntry(LocInfo.first).getFile();
+ bool Invalid = false;
+ const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);
+ if (Invalid || !Entry.isFile())
+ return PresumedLoc();
+
+ const SrcMgr::FileInfo &FI = Entry.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;
- if (C->Entry)
- Filename = C->Entry->getName();
+ if (C->OrigEntry)
+ Filename = C->OrigEntry->getName();
else
Filename = C->getBuffer(Diag, *this)->getBufferIdentifier();
- bool Invalid = false;
+
unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &Invalid);
if (Invalid)
return PresumedLoc();
@@ -1152,18 +1243,22 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile,
llvm::Optional<ino_t> SourceFileInode;
llvm::Optional<llvm::StringRef> SourceFileName;
if (!MainFileID.isInvalid()) {
- const SLocEntry &MainSLoc = getSLocEntry(MainFileID);
+ bool Invalid = false;
+ const SLocEntry &MainSLoc = getSLocEntry(MainFileID, &Invalid);
+ if (Invalid)
+ return SourceLocation();
+
if (MainSLoc.isFile()) {
const ContentCache *MainContentCache
= MainSLoc.getFile().getContentCache();
if (!MainContentCache) {
// Can't do anything
- } else if (MainContentCache->Entry == SourceFile) {
+ } else if (MainContentCache->OrigEntry == SourceFile) {
FirstFID = MainFileID;
} else {
// Fall back: check whether we have the same base name and inode
// as the main file.
- const FileEntry *MainFile = MainContentCache->Entry;
+ const FileEntry *MainFile = MainContentCache->OrigEntry;
SourceFileName = llvm::sys::path::filename(SourceFile->getName());
if (*SourceFileName == llvm::sys::path::filename(MainFile->getName())) {
SourceFileInode = getActualFileInode(SourceFile);
@@ -1185,10 +1280,14 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile,
// The location we're looking for isn't in the main file; look
// through all of the source locations.
for (unsigned I = 0, N = sloc_entry_size(); I != N; ++I) {
- const SLocEntry &SLoc = getSLocEntry(I);
+ bool Invalid = false;
+ const SLocEntry &SLoc = getSLocEntry(I, &Invalid);
+ if (Invalid)
+ return SourceLocation();
+
if (SLoc.isFile() &&
SLoc.getFile().getContentCache() &&
- SLoc.getFile().getContentCache()->Entry == SourceFile) {
+ SLoc.getFile().getContentCache()->OrigEntry == SourceFile) {
FirstFID = FileID::get(I);
break;
}
@@ -1203,12 +1302,16 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile,
(SourceFileName = llvm::sys::path::filename(SourceFile->getName()))) &&
(SourceFileInode ||
(SourceFileInode = getActualFileInode(SourceFile)))) {
+ bool Invalid = false;
for (unsigned I = 0, N = sloc_entry_size(); I != N; ++I) {
- const SLocEntry &SLoc = getSLocEntry(I);
+ const SLocEntry &SLoc = getSLocEntry(I, &Invalid);
+ if (Invalid)
+ return SourceLocation();
+
if (SLoc.isFile()) {
const ContentCache *FileContentCache
= SLoc.getFile().getContentCache();
- const FileEntry *Entry =FileContentCache? FileContentCache->Entry : 0;
+ const FileEntry *Entry =FileContentCache? FileContentCache->OrigEntry : 0;
if (Entry &&
*SourceFileName == llvm::sys::path::filename(Entry->getName())) {
if (llvm::Optional<ino_t> EntryInode = getActualFileInode(Entry)) {
@@ -1367,7 +1470,7 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
while (!MoveUpIncludeHierarchy(LOffs, *this)) /*empty*/;
while (!MoveUpIncludeHierarchy(ROffs, *this)) /*empty*/;
- // If exactly one location is a memory buffer, assume it preceeds the other.
+ // If exactly one location is a memory buffer, assume it precedes the other.
// Strip off macro instantation locations, going up to the top-level File
// SLocEntry.
@@ -1403,3 +1506,24 @@ void SourceManager::PrintStats() const {
}
ExternalSLocEntrySource::~ExternalSLocEntrySource() { }
+
+/// Return the amount of memory used by memory buffers, breaking down
+/// by heap-backed versus mmap'ed memory.
+SourceManager::MemoryBufferSizes SourceManager::getMemoryBufferSizes() const {
+ size_t malloc_bytes = 0;
+ size_t mmap_bytes = 0;
+
+ for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i)
+ if (size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped())
+ switch (MemBufferInfos[i]->getMemoryBufferKind()) {
+ case llvm::MemoryBuffer::MemoryBuffer_MMap:
+ mmap_bytes += sized_mapped;
+ break;
+ case llvm::MemoryBuffer::MemoryBuffer_Malloc:
+ malloc_bytes += sized_mapped;
+ break;
+ }
+
+ return MemoryBufferSizes(malloc_bytes, mmap_bytes);
+}
+
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index a9eeb8b..dcf0cb4 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/APFloat.h"
@@ -19,6 +20,8 @@
#include <cstdlib>
using namespace clang;
+static const LangAS::Map DefaultAddrSpaceMap = { 0 };
+
// TargetInfo Constructor.
TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
// Set defaults. Defaults are set for a 32-bit RISC platform, like PPC or
@@ -64,6 +67,13 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
// Default to using the Itanium ABI.
CXXABI = CXXABI_Itanium;
+
+ // Default to an empty address space map.
+ AddrSpaceMap = &DefaultAddrSpaceMap;
+
+ // Default to an unknown platform name.
+ PlatformName = "unknown";
+ PlatformMinVersion = VersionTuple();
}
// Out of line virtual dtor for TargetInfo.
@@ -422,7 +432,7 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints,
case ',': // multiple alternative constraint. Ignore comma.
break;
case '?': // Disparage slightly code.
- case '!': // Disparage severly.
+ case '!': // Disparage severely.
break; // Pass them.
}
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 55321f24..97109ca 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -76,7 +76,9 @@ public:
static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
- const llvm::Triple &Triple) {
+ const llvm::Triple &Triple,
+ llvm::StringRef &PlatformName,
+ VersionTuple &PlatformMinVersion) {
Builder.defineMacro("__APPLE_CC__", "5621");
Builder.defineMacro("__APPLE__");
Builder.defineMacro("__MACH__");
@@ -99,19 +101,40 @@ static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
if (Opts.POSIXThreads)
Builder.defineMacro("_REENTRANT");
- // Get the OS version number from the triple.
+ // Get the platform type and version number from the triple.
unsigned Maj, Min, Rev;
// If no version was given, default to to 10.4.0, for simplifying tests.
- if (Triple.getOSName() == "darwin") {
+ if (Triple.getOSName() == "darwin" || Triple.getOSName() == "osx") {
+ PlatformName = "macosx";
Min = Rev = 0;
Maj = 8;
- } else
- Triple.getDarwinNumber(Maj, Min, Rev);
+ } else {
+ // Otherwise, honor all three triple forms ("-darwinNNN[-iphoneos]",
+ // "-osxNNN", and "-iosNNN").
+
+ if (Triple.getOS() == llvm::Triple::Darwin) {
+ // For historical reasons that make little sense, the version passed here
+ // is the "darwin" version, which drops the 10 and offsets by 4.
+ Triple.getOSVersion(Maj, Min, Rev);
+
+ if (Triple.getEnvironmentName() == "iphoneos") {
+ PlatformName = "ios";
+ } else {
+ PlatformName = "macosx";
+ Rev = Min;
+ Min = Maj - 4;
+ Maj = 10;
+ }
+ } else {
+ Triple.getOSVersion(Maj, Min, Rev);
+ PlatformName = llvm::Triple::getOSTypeName(Triple.getOS());
+ }
+ }
// Set the appropriate OS version define.
- if (Triple.getEnvironmentName() == "iphoneos") {
- assert(Maj < 10 && Min < 99 && Rev < 99 && "Invalid version!");
+ if (PlatformName == "ios") {
+ assert(Maj < 10 && Min < 100 && Rev < 100 && "Invalid version!");
char Str[6];
Str[0] = '0' + Maj;
Str[1] = '0' + (Min / 10);
@@ -121,22 +144,22 @@ static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
Str[5] = '\0';
Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__", Str);
} else {
- // For historical reasons that make little sense, the version passed here is
- // the "darwin" version, which drops the 10 and offsets by 4.
- Rev = Min;
- Min = Maj - 4;
- Maj = 10;
-
+ // Note that the Driver allows versions which aren't representable in the
+ // define (because we only get a single digit for the minor and micro
+ // revision numbers). So, we limit them to the maximum representable
+ // version.
assert(Triple.getEnvironmentName().empty() && "Invalid environment!");
- assert(Maj < 99 && Min < 10 && Rev < 10 && "Invalid version!");
+ assert(Maj < 100 && Min < 100 && Rev < 100 && "Invalid version!");
char Str[5];
Str[0] = '0' + (Maj / 10);
Str[1] = '0' + (Maj % 10);
- Str[2] = '0' + Min;
- Str[3] = '0' + Rev;
+ Str[2] = '0' + std::min(Min, 9U);
+ Str[3] = '0' + std::min(Rev, 9U);
Str[4] = '\0';
Builder.defineMacro("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", Str);
}
+
+ PlatformMinVersion = VersionTuple(Maj, Min, Rev);
}
namespace {
@@ -145,7 +168,8 @@ class DarwinTargetInfo : public OSTargetInfo<Target> {
protected:
virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const {
- getDarwinDefines(Builder, Opts, Triple);
+ getDarwinDefines(Builder, Opts, Triple, this->PlatformName,
+ this->PlatformMinVersion);
}
public:
@@ -159,8 +183,9 @@ public:
// Let MCSectionMachO validate this.
llvm::StringRef Segment, Section;
unsigned TAA, StubSize;
+ bool HasTAA;
return llvm::MCSectionMachO::ParseSectionSpecifier(SR, Segment, Section,
- TAA, StubSize);
+ TAA, HasTAA, StubSize);
}
virtual const char *getStaticInitSectionSpecifier() const {
@@ -823,6 +848,87 @@ public:
} // end anonymous namespace.
namespace {
+ class PTXTargetInfo : public TargetInfo {
+ static const char * const GCCRegNames[];
+ static const Builtin::Info BuiltinInfo[];
+ public:
+ PTXTargetInfo(const std::string& triple) : TargetInfo(triple) {
+ TLSSupported = false;
+ LongWidth = LongAlign = 64;
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__PTX__");
+ }
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const {
+ Records = BuiltinInfo;
+ NumRecords = clang::PTX::LastTSBuiltin-Builtin::FirstTSBuiltin;
+ }
+
+ 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 Builtin::Info PTXTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES, false },
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\
+ ALL_LANGUAGES, false },
+#include "clang/Basic/BuiltinsPTX.def"
+ };
+
+ const char * const PTXTargetInfo::GCCRegNames[] = {
+ "r0"
+ };
+
+ void PTXTargetInfo::getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
+ Names = GCCRegNames;
+ NumNames = llvm::array_lengthof(GCCRegNames);
+ }
+
+
+ class PTX32TargetInfo : public PTXTargetInfo {
+ public:
+ PTX32TargetInfo(const std::string& triple) : PTXTargetInfo(triple) {
+ PointerWidth = PointerAlign = 32;
+ SizeType = PtrDiffType = IntPtrType = TargetInfo::UnsignedInt;
+ DescriptionString
+ = "e-p:32:32-i64:64:64-f64:64:64-n1:8:16:32:64";
+ }
+ };
+
+ class PTX64TargetInfo : public PTXTargetInfo {
+ public:
+ PTX64TargetInfo(const std::string& triple) : PTXTargetInfo(triple) {
+ PointerWidth = PointerAlign = 64;
+ SizeType = PtrDiffType = IntPtrType = TargetInfo::UnsignedLongLong;
+ DescriptionString
+ = "e-p:64:64-i64:64:64-f64:64:64-n1:8:16:32:64";
+ }
+ };
+}
+
+namespace {
// MBlaze abstract base class
class MBlazeTargetInfo : public TargetInfo {
static const char * const GCCRegNames[];
@@ -1074,8 +1180,11 @@ void X86TargetInfo::getDefaultFeatures(const std::string &CPU,
else if (CPU == "corei7") {
setFeatureEnabled(Features, "sse4", true);
setFeatureEnabled(Features, "aes", true);
- }
- else if (CPU == "k6" || CPU == "winchip-c6")
+ } else if (CPU == "sandybridge") {
+ setFeatureEnabled(Features, "sse4", true);
+ setFeatureEnabled(Features, "aes", true);
+// setFeatureEnabled(Features, "avx", true);
+ } else if (CPU == "k6" || CPU == "winchip-c6")
setFeatureEnabled(Features, "mmx", true);
else if (CPU == "k6-2" || CPU == "k6-3" || CPU == "athlon" ||
CPU == "athlon-tbird" || CPU == "winchip2" || CPU == "c3") {
@@ -1133,7 +1242,8 @@ bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
Features["avx"] = true;
} else {
if (Name == "mmx")
- Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] =
+ Features["mmx"] = Features["3dnow"] = Features["3dnowa"] =
+ Features["sse"] = Features["sse2"] = Features["sse3"] =
Features["ssse3"] = Features["sse41"] = Features["sse42"] = false;
else if (Name == "sse")
Features["sse"] = Features["sse2"] = Features["sse3"] =
@@ -1146,12 +1256,10 @@ bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
Features["sse42"] = false;
else if (Name == "ssse3")
Features["ssse3"] = Features["sse41"] = Features["sse42"] = false;
- else if (Name == "sse4")
+ else if (Name == "sse4" || Name == "sse4.1")
Features["sse41"] = Features["sse42"] = false;
else if (Name == "sse4.2")
Features["sse42"] = false;
- else if (Name == "sse4.1")
- Features["sse41"] = Features["sse42"] = false;
else if (Name == "3dnow")
Features["3dnow"] = Features["3dnowa"] = false;
else if (Name == "3dnowa")
@@ -1451,7 +1559,7 @@ class VisualStudioWindowsX86_32TargetInfo : public WindowsX86_32TargetInfo {
public:
VisualStudioWindowsX86_32TargetInfo(const std::string& triple)
: WindowsX86_32TargetInfo(triple) {
- LongDoubleWidth = 64;
+ LongDoubleWidth = LongDoubleAlign = 64;
LongDoubleFormat = &llvm::APFloat::IEEEdouble;
}
virtual void getTargetDefines(const LangOptions &Opts,
@@ -1481,7 +1589,15 @@ public:
Builder.defineMacro("_X86_");
Builder.defineMacro("__MSVCRT__");
Builder.defineMacro("__MINGW32__");
- Builder.defineMacro("__declspec", "__declspec");
+
+ // mingw32-gcc provides __declspec(a) as alias of __attribute__((a)).
+ // In contrast, clang-cc1 provides __declspec(a) with -fms-extensions.
+ if (Opts.Microsoft)
+ // Provide "as-is" __declspec.
+ Builder.defineMacro("__declspec", "__declspec");
+ else
+ // Provide alias of __attribute__ like mingw32-gcc.
+ Builder.defineMacro("__declspec(a)", "__attribute__((a))");
}
};
} // end anonymous namespace
@@ -1606,6 +1722,8 @@ class VisualStudioWindowsX86_64TargetInfo : public WindowsX86_64TargetInfo {
public:
VisualStudioWindowsX86_64TargetInfo(const std::string& triple)
: WindowsX86_64TargetInfo(triple) {
+ LongDoubleWidth = LongDoubleAlign = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble;
}
virtual void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
@@ -1629,8 +1747,17 @@ public:
WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder);
DefineStd(Builder, "WIN64", Opts);
Builder.defineMacro("__MSVCRT__");
+ Builder.defineMacro("__MINGW32__");
Builder.defineMacro("__MINGW64__");
- Builder.defineMacro("__declspec", "__declspec");
+
+ // mingw32-gcc provides __declspec(a) as alias of __attribute__((a)).
+ // In contrast, clang-cc1 provides __declspec(a) with -fms-extensions.
+ if (Opts.Microsoft)
+ // Provide "as-is" __declspec.
+ Builder.defineMacro("__declspec", "__declspec");
+ else
+ // Provide alias of __attribute__ like mingw32-gcc.
+ Builder.defineMacro("__declspec(a)", "__attribute__((a))");
}
};
} // end anonymous namespace
@@ -1700,13 +1827,15 @@ public:
// FIXME: Should we just treat this as a feature?
IsThumb = getTriple().getArchName().startswith("thumb");
if (IsThumb) {
+ // Thumb1 add sp, #imm requires the immediate value be multiple of 4,
+ // so set preferred for small types to 32.
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-n32");
+ "v64:64:64-v128:64:128-a0:0:32-n32");
} 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-n32");
+ "v64:64:64-v128:64:128-a0:0:64-n32");
}
// ARM targets default to using the ARM C++ ABI.
@@ -1729,13 +1858,15 @@ public:
UseBitFieldTypeAlignment = false;
if (IsThumb) {
+ // Thumb1 add sp, #imm requires the immediate value be multiple of 4,
+ // so set preferred for small types to 32.
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-n32");
+ "v64:32:64-v128:32:128-a0:0:32-n32");
} 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-n32");
+ "i64:32:64-f32:32:32-f64:32:64-"
+ "v64:32:64-v128:32:128-a0:0:32-n32");
}
// FIXME: Override "preferred align" for double and long long.
@@ -1822,6 +1953,7 @@ public:
.Cases("arm1156t2-s", "arm1156t2f-s", "6T2")
.Cases("cortex-a8", "cortex-a9", "7A")
.Case("cortex-m3", "7M")
+ .Case("cortex-m0", "6M")
.Default(0);
}
virtual bool setCPU(const std::string &Name) {
@@ -1984,7 +2116,7 @@ class DarwinARMTargetInfo :
protected:
virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const {
- getDarwinDefines(Builder, Opts, Triple);
+ getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
}
public:
@@ -2563,11 +2695,12 @@ static TargetInfo *AllocateTarget(const std::string &T) {
case llvm::Triple::arm:
case llvm::Triple::thumb:
+ if (Triple.isOSDarwin())
+ return new DarwinARMTargetInfo(T);
+
switch (os) {
case llvm::Triple::Linux:
return new LinuxTargetInfo<ARMTargetInfo>(T);
- case llvm::Triple::Darwin:
- return new DarwinARMTargetInfo(T);
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<ARMTargetInfo>(T);
default:
@@ -2595,14 +2728,14 @@ static TargetInfo *AllocateTarget(const std::string &T) {
return new MipselTargetInfo(T);
case llvm::Triple::ppc:
- if (os == llvm::Triple::Darwin)
+ if (Triple.isOSDarwin())
return new DarwinPPC32TargetInfo(T);
else if (os == llvm::Triple::FreeBSD)
return new FreeBSDTargetInfo<PPC32TargetInfo>(T);
return new PPC32TargetInfo(T);
case llvm::Triple::ppc64:
- if (os == llvm::Triple::Darwin)
+ if (Triple.isOSDarwin())
return new DarwinPPC64TargetInfo(T);
else if (os == llvm::Triple::Lv2)
return new PS3PPUTargetInfo<PPC64TargetInfo>(T);
@@ -2610,6 +2743,11 @@ static TargetInfo *AllocateTarget(const std::string &T) {
return new FreeBSDTargetInfo<PPC64TargetInfo>(T);
return new PPC64TargetInfo(T);
+ case llvm::Triple::ptx32:
+ return new PTX32TargetInfo(T);
+ case llvm::Triple::ptx64:
+ return new PTX64TargetInfo(T);
+
case llvm::Triple::mblaze:
return new MBlazeTargetInfo(T);
@@ -2631,11 +2769,12 @@ static TargetInfo *AllocateTarget(const std::string &T) {
return new TCETargetInfo(T);
case llvm::Triple::x86:
+ if (Triple.isOSDarwin())
+ return new DarwinI386TargetInfo(T);
+
switch (os) {
case llvm::Triple::AuroraUX:
return new AuroraUXTargetInfo<X86_32TargetInfo>(T);
- case llvm::Triple::Darwin:
- return new DarwinI386TargetInfo(T);
case llvm::Triple::Linux:
return new LinuxTargetInfo<X86_32TargetInfo>(T);
case llvm::Triple::DragonFly:
@@ -2663,11 +2802,12 @@ static TargetInfo *AllocateTarget(const std::string &T) {
}
case llvm::Triple::x86_64:
+ if (Triple.isOSDarwin() || Triple.getEnvironment() == llvm::Triple::MachO)
+ return new DarwinX86_64TargetInfo(T);
+
switch (os) {
case llvm::Triple::AuroraUX:
return new AuroraUXTargetInfo<X86_64TargetInfo>(T);
- case llvm::Triple::Darwin:
- return new DarwinX86_64TargetInfo(T);
case llvm::Triple::Linux:
return new LinuxTargetInfo<X86_64TargetInfo>(T);
case llvm::Triple::DragonFly:
@@ -2683,10 +2823,7 @@ static TargetInfo *AllocateTarget(const std::string &T) {
case llvm::Triple::MinGW32:
return new MinGWX86_64TargetInfo(T);
case llvm::Triple::Win32: // This is what Triple.h supports now.
- if (Triple.getEnvironment() == llvm::Triple::MachO)
- return new DarwinX86_64TargetInfo(T);
- else
- return new VisualStudioWindowsX86_64TargetInfo(T);
+ return new VisualStudioWindowsX86_64TargetInfo(T);
default:
return new X86_64TargetInfo(T);
}
diff --git a/lib/Basic/Version.cpp b/lib/Basic/Version.cpp
index 6573eb9..8f71352 100644
--- a/lib/Basic/Version.cpp
+++ b/lib/Basic/Version.cpp
@@ -17,11 +17,12 @@
#include <cstring>
#include <cstdlib>
-using namespace std;
-
namespace clang {
std::string getClangRepositoryPath() {
+#if defined(CLANG_REPOSITORY_STRING)
+ return CLANG_REPOSITORY_STRING;
+#else
#ifdef SVN_REPOSITORY
llvm::StringRef URL(SVN_REPOSITORY);
#else
@@ -45,6 +46,7 @@ std::string getClangRepositoryPath() {
URL = URL.substr(Start + 4);
return URL;
+#endif
}
std::string getClangRevision() {
@@ -87,4 +89,17 @@ std::string getClangFullVersion() {
return OS.str();
}
+std::string getClangFullCPPVersion() {
+ // The version string we report in __VERSION__ is just a compacted version of
+ // the one we report on the command line.
+ std::string buf;
+ llvm::raw_string_ostream OS(buf);
+#ifdef CLANG_VENDOR
+ OS << CLANG_VENDOR;
+#endif
+ OS << "Clang " CLANG_VERSION_STRING " ("
+ << getClangFullRepositoryVersion() << ')';
+ return OS.str();
+}
+
} // end namespace clang
diff --git a/lib/Basic/VersionTuple.cpp b/lib/Basic/VersionTuple.cpp
new file mode 100644
index 0000000..d5cf126
--- /dev/null
+++ b/lib/Basic/VersionTuple.cpp
@@ -0,0 +1,36 @@
+//===- VersionTuple.cpp - Version Number Handling ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the VersionTuple class, which represents a version in
+// the form major[.minor[.subminor]].
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Basic/VersionTuple.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+
+std::string VersionTuple::getAsString() const {
+ std::string Result;
+ {
+ llvm::raw_string_ostream Out(Result);
+ Out << *this;
+ }
+ return Result;
+}
+
+llvm::raw_ostream& clang::operator<<(llvm::raw_ostream &Out,
+ const VersionTuple &V) {
+ Out << V.getMajor();
+ if (llvm::Optional<unsigned> Minor = V.getMinor())
+ Out << '.' << *Minor;
+ if (llvm::Optional<unsigned> Subminor = V.getSubminor())
+ Out << '.' << *Subminor;
+ return Out;
+}
OpenPOWER on IntegriCloud