diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Basic')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Basic/Builtins.cpp | 10 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp | 239 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp | 397 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Basic/FileManager.cpp | 50 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp | 47 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp | 30 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp | 22 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp | 797 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp | 29 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Basic/Targets.cpp | 1098 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Basic/Version.cpp | 9 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Basic/VersionTuple.cpp | 2 |
12 files changed, 1957 insertions, 773 deletions
diff --git a/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp b/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp index 7df24a0..7bdcdc6 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp @@ -32,11 +32,15 @@ const Builtin::Info &Builtin::Context::GetRecord(unsigned ID) const { return TSRecords[ID - Builtin::FirstTSBuiltin]; } -Builtin::Context::Context(const TargetInfo &Target) { +Builtin::Context::Context() { // Get the target specific builtins from the target. TSRecords = 0; NumTSRecords = 0; - Target.getTargetBuiltins(TSRecords, NumTSRecords); +} + +void Builtin::Context::InitializeTarget(const TargetInfo &Target) { + assert(NumTSRecords == 0 && "Already initialized target?"); + Target.getTargetBuiltins(TSRecords, NumTSRecords); } /// InitializeBuiltins - Mark the identifiers for all the builtins with their @@ -59,7 +63,7 @@ void Builtin::Context::InitializeBuiltins(IdentifierTable &Table, } void -Builtin::Context::GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names, +Builtin::Context::GetBuiltinNames(SmallVectorImpl<const char *> &Names, bool NoBuiltins) { // Final all target-independent names for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i) diff --git a/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp index ae363a0..e5f3901 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp @@ -20,21 +20,22 @@ using namespace clang; -static void DummyArgToStringFn(Diagnostic::ArgumentKind AK, intptr_t QT, +static void DummyArgToStringFn(DiagnosticsEngine::ArgumentKind AK, intptr_t QT, const char *Modifier, unsigned ML, const char *Argument, unsigned ArgLen, - const Diagnostic::ArgumentValue *PrevArgs, + const DiagnosticsEngine::ArgumentValue *PrevArgs, unsigned NumPrevArgs, - llvm::SmallVectorImpl<char> &Output, + SmallVectorImpl<char> &Output, void *Cookie, - llvm::SmallVectorImpl<intptr_t> &QualTypeVals) { + SmallVectorImpl<intptr_t> &QualTypeVals) { const char *Str = "<can't format argument>"; Output.append(Str, Str+strlen(Str)); } -Diagnostic::Diagnostic(const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &diags, - DiagnosticClient *client, bool ShouldOwnClient) +DiagnosticsEngine::DiagnosticsEngine( + const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &diags, + DiagnosticConsumer *client, bool ShouldOwnClient) : Diags(diags), Client(client), OwnsDiagClient(ShouldOwnClient), SourceMgr(0) { ArgToStringFn = DummyArgToStringFn; @@ -43,6 +44,7 @@ Diagnostic::Diagnostic(const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &diags, AllExtensionsSilenced = 0; IgnoreAllWarnings = false; WarningsAsErrors = false; + EnableAllWarnings = false; ErrorsAsFatal = false; SuppressSystemWarnings = false; SuppressAllDiagnostics = false; @@ -55,12 +57,13 @@ Diagnostic::Diagnostic(const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &diags, Reset(); } -Diagnostic::~Diagnostic() { +DiagnosticsEngine::~DiagnosticsEngine() { if (OwnsDiagClient) delete Client; } -void Diagnostic::setClient(DiagnosticClient *client, bool ShouldOwnClient) { +void DiagnosticsEngine::setClient(DiagnosticConsumer *client, + bool ShouldOwnClient) { if (OwnsDiagClient && Client) delete Client; @@ -68,11 +71,11 @@ void Diagnostic::setClient(DiagnosticClient *client, bool ShouldOwnClient) { OwnsDiagClient = ShouldOwnClient; } -void Diagnostic::pushMappings(SourceLocation Loc) { +void DiagnosticsEngine::pushMappings(SourceLocation Loc) { DiagStateOnPushStack.push_back(GetCurDiagState()); } -bool Diagnostic::popMappings(SourceLocation Loc) { +bool DiagnosticsEngine::popMappings(SourceLocation Loc) { if (DiagStateOnPushStack.empty()) return false; @@ -84,7 +87,7 @@ bool Diagnostic::popMappings(SourceLocation Loc) { return true; } -void Diagnostic::Reset() { +void DiagnosticsEngine::Reset() { ErrorOccurred = false; FatalErrorOccurred = false; UnrecoverableErrorOccurred = false; @@ -92,11 +95,13 @@ void Diagnostic::Reset() { NumWarnings = 0; NumErrors = 0; NumErrorsSuppressed = 0; + TrapNumErrorsOccurred = 0; + TrapNumUnrecoverableErrorsOccurred = 0; CurDiagID = ~0U; // Set LastDiagLevel to an "unset" state. If we set it to 'Ignored', notes - // using a Diagnostic associated to a translation unit that follow - // diagnostics from a Diagnostic associated to anoter t.u. will not be + // using a DiagnosticsEngine associated to a translation unit that follow + // diagnostics from a DiagnosticsEngine associated to anoter t.u. will not be // displayed. LastDiagLevel = (DiagnosticIDs::Level)-1; DelayedDiagID = 0; @@ -112,8 +117,8 @@ void Diagnostic::Reset() { PushDiagStatePoint(&DiagStates.back(), SourceLocation()); } -void Diagnostic::SetDelayedDiagnostic(unsigned DiagID, llvm::StringRef Arg1, - llvm::StringRef Arg2) { +void DiagnosticsEngine::SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1, + StringRef Arg2) { if (DelayedDiagID) return; @@ -122,15 +127,15 @@ void Diagnostic::SetDelayedDiagnostic(unsigned DiagID, llvm::StringRef Arg1, DelayedDiagArg2 = Arg2.str(); } -void Diagnostic::ReportDelayed() { +void DiagnosticsEngine::ReportDelayed() { Report(DelayedDiagID) << DelayedDiagArg1 << DelayedDiagArg2; DelayedDiagID = 0; DelayedDiagArg1.clear(); DelayedDiagArg2.clear(); } -Diagnostic::DiagStatePointsTy::iterator -Diagnostic::GetDiagStatePointForLoc(SourceLocation L) const { +DiagnosticsEngine::DiagStatePointsTy::iterator +DiagnosticsEngine::GetDiagStatePointForLoc(SourceLocation L) const { assert(!DiagStatePoints.empty()); assert(DiagStatePoints.front().Loc.isInvalid() && "Should have created a DiagStatePoint for command-line"); @@ -155,7 +160,7 @@ Diagnostic::GetDiagStatePointForLoc(SourceLocation L) const { /// /// \param The source location that this change of diagnostic state should /// take affect. It can be null if we are setting the latest state. -void Diagnostic::setDiagnosticMapping(diag::kind Diag, diag::Mapping Map, +void DiagnosticsEngine::setDiagnosticMapping(diag::kind Diag, diag::Mapping Map, SourceLocation L) { assert(Diag < diag::DIAG_UPPER_LIMIT && "Can only map builtin diagnostics"); @@ -167,10 +172,19 @@ void Diagnostic::setDiagnosticMapping(diag::kind Diag, diag::Mapping Map, bool isPragma = L.isValid(); FullSourceLoc Loc(L, *SourceMgr); FullSourceLoc LastStateChangePos = DiagStatePoints.back().Loc; + DiagnosticMappingInfo MappingInfo = DiagnosticMappingInfo::Make( + Map, /*IsUser=*/true, isPragma); + + // If this is a pragma mapping, then set the diagnostic mapping flags so that + // we override command line options. + if (isPragma) { + MappingInfo.setNoWarningAsError(true); + MappingInfo.setNoErrorAsFatal(true); + } // Common case; setting all the diagnostics of a group in one place. if (Loc.isInvalid() || Loc == LastStateChangePos) { - setDiagnosticMappingInternal(Diag, Map, GetCurDiagState(), true, isPragma); + GetCurDiagState()->setMappingInfo(Diag, MappingInfo); return; } @@ -183,7 +197,7 @@ void Diagnostic::setDiagnosticMapping(diag::kind Diag, diag::Mapping Map, // the new state became active. DiagStates.push_back(*GetCurDiagState()); PushDiagStatePoint(&DiagStates.back(), Loc); - setDiagnosticMappingInternal(Diag, Map, GetCurDiagState(), true, isPragma); + GetCurDiagState()->setMappingInfo(Diag, MappingInfo); return; } @@ -196,12 +210,12 @@ void Diagnostic::setDiagnosticMapping(diag::kind Diag, diag::Mapping Map, // Update all diagnostic states that are active after the given location. for (DiagStatePointsTy::iterator I = Pos+1, E = DiagStatePoints.end(); I != E; ++I) { - setDiagnosticMappingInternal(Diag, Map, I->State, true, isPragma); + GetCurDiagState()->setMappingInfo(Diag, MappingInfo); } // If the location corresponds to an existing point, just update its state. if (Pos->Loc == Loc) { - setDiagnosticMappingInternal(Diag, Map, Pos->State, true, isPragma); + GetCurDiagState()->setMappingInfo(Diag, MappingInfo); return; } @@ -210,12 +224,86 @@ void Diagnostic::setDiagnosticMapping(diag::kind Diag, diag::Mapping Map, Pos->Loc.isBeforeInTranslationUnitThan(Loc); DiagStates.push_back(*Pos->State); DiagState *NewState = &DiagStates.back(); - setDiagnosticMappingInternal(Diag, Map, NewState, true, isPragma); + GetCurDiagState()->setMappingInfo(Diag, MappingInfo); DiagStatePoints.insert(Pos+1, DiagStatePoint(NewState, FullSourceLoc(Loc, *SourceMgr))); } -void Diagnostic::Report(const StoredDiagnostic &storedDiag) { +bool DiagnosticsEngine::setDiagnosticGroupMapping( + StringRef Group, diag::Mapping Map, SourceLocation Loc) +{ + // Get the diagnostics in this group. + llvm::SmallVector<diag::kind, 8> GroupDiags; + if (Diags->getDiagnosticsInGroup(Group, GroupDiags)) + return true; + + // Set the mapping. + for (unsigned i = 0, e = GroupDiags.size(); i != e; ++i) + setDiagnosticMapping(GroupDiags[i], Map, Loc); + + return false; +} + +bool DiagnosticsEngine::setDiagnosticGroupWarningAsError(StringRef Group, + bool Enabled) { + // If we are enabling this feature, just set the diagnostic mappings to map to + // errors. + if (Enabled) + return setDiagnosticGroupMapping(Group, diag::MAP_ERROR); + + // Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and + // potentially downgrade anything already mapped to be a warning. + + // Get the diagnostics in this group. + llvm::SmallVector<diag::kind, 8> GroupDiags; + if (Diags->getDiagnosticsInGroup(Group, GroupDiags)) + return true; + + // Perform the mapping change. + for (unsigned i = 0, e = GroupDiags.size(); i != e; ++i) { + DiagnosticMappingInfo &Info = GetCurDiagState()->getOrAddMappingInfo( + GroupDiags[i]); + + if (Info.getMapping() == diag::MAP_ERROR || + Info.getMapping() == diag::MAP_FATAL) + Info.setMapping(diag::MAP_WARNING); + + Info.setNoWarningAsError(true); + } + + return false; +} + +bool DiagnosticsEngine::setDiagnosticGroupErrorAsFatal(StringRef Group, + bool Enabled) { + // If we are enabling this feature, just set the diagnostic mappings to map to + // fatal errors. + if (Enabled) + return setDiagnosticGroupMapping(Group, diag::MAP_FATAL); + + // Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and + // potentially downgrade anything already mapped to be an error. + + // Get the diagnostics in this group. + llvm::SmallVector<diag::kind, 8> GroupDiags; + if (Diags->getDiagnosticsInGroup(Group, GroupDiags)) + return true; + + // Perform the mapping change. + for (unsigned i = 0, e = GroupDiags.size(); i != e; ++i) { + DiagnosticMappingInfo &Info = GetCurDiagState()->getOrAddMappingInfo( + GroupDiags[i]); + + if (Info.getMapping() == diag::MAP_FATAL) + Info.setMapping(diag::MAP_ERROR); + + Info.setNoErrorAsFatal(true); + } + + return false; +} + +void DiagnosticsEngine::Report(const StoredDiagnostic &storedDiag) { assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!"); CurDiagLoc = storedDiag.getLocation(); @@ -232,19 +320,20 @@ void Diagnostic::Report(const StoredDiagnostic &storedDiag) { DiagRanges[i++] = *RI; NumFixItHints = storedDiag.fixit_size(); - assert(NumFixItHints < Diagnostic::MaxFixItHints && "Too many fix-it hints!"); + assert(NumFixItHints < DiagnosticsEngine::MaxFixItHints && + "Too many fix-it hints!"); i = 0; for (StoredDiagnostic::fixit_iterator FI = storedDiag.fixit_begin(), FE = storedDiag.fixit_end(); FI != FE; ++FI) FixItHints[i++] = *FI; - assert(Client && "DiagnosticClient not set!"); + assert(Client && "DiagnosticConsumer not set!"); Level DiagLevel = storedDiag.getLevel(); - DiagnosticInfo Info(this, storedDiag.getMessage()); + Diagnostic Info(this, storedDiag.getMessage()); Client->HandleDiagnostic(DiagLevel, Info); if (Client->IncludeInDiagnosticCounts()) { - if (DiagLevel == Diagnostic::Warning) + if (DiagLevel == DiagnosticsEngine::Warning) ++NumWarnings; } @@ -263,11 +352,11 @@ bool DiagnosticBuilder::Emit() { if (DiagObj == 0) return false; // When emitting diagnostics, we set the final argument count into - // the Diagnostic object. + // the DiagnosticsEngine object. FlushCounts(); // Process the diagnostic, sending the accumulated information to the - // DiagnosticClient. + // DiagnosticConsumer. bool Emitted = DiagObj->ProcessDiag(); // Clear out the current diagnostic object. @@ -285,16 +374,16 @@ bool DiagnosticBuilder::Emit() { } -DiagnosticClient::~DiagnosticClient() {} +DiagnosticConsumer::~DiagnosticConsumer() {} -void DiagnosticClient::HandleDiagnostic(Diagnostic::Level DiagLevel, - const DiagnosticInfo &Info) { +void DiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, + const Diagnostic &Info) { if (!IncludeInDiagnosticCounts()) return; - if (DiagLevel == Diagnostic::Warning) + if (DiagLevel == DiagnosticsEngine::Warning) ++NumWarnings; - else if (DiagLevel >= Diagnostic::Error) + else if (DiagLevel >= DiagnosticsEngine::Error) ++NumErrors; } @@ -337,9 +426,9 @@ static const char *ScanFormat(const char *I, const char *E, char Target) { /// "%2" has a value from 0-2. If the value is 0, the diagnostic prints 'foo'. /// If the value is 1, it prints 'bar'. If it has the value 2, it prints 'baz'. /// This is very useful for certain classes of variant diagnostics. -static void HandleSelectModifier(const DiagnosticInfo &DInfo, unsigned ValNo, +static void HandleSelectModifier(const Diagnostic &DInfo, unsigned ValNo, const char *Argument, unsigned ArgumentLen, - llvm::SmallVectorImpl<char> &OutStr) { + SmallVectorImpl<char> &OutStr) { const char *ArgumentEnd = Argument+ArgumentLen; // Skip over 'ValNo' |'s. @@ -362,7 +451,7 @@ static void HandleSelectModifier(const DiagnosticInfo &DInfo, unsigned ValNo, /// letter 's' to the string if the value is not 1. This is used in cases like /// this: "you idiot, you have %4 parameter%s4!". static void HandleIntegerSModifier(unsigned ValNo, - llvm::SmallVectorImpl<char> &OutStr) { + SmallVectorImpl<char> &OutStr) { if (ValNo != 1) OutStr.push_back('s'); } @@ -372,7 +461,7 @@ static void HandleIntegerSModifier(unsigned ValNo, /// to the first ordinal. Currently this is hard-coded to use the /// English form. static void HandleOrdinalModifier(unsigned ValNo, - llvm::SmallVectorImpl<char> &OutStr) { + SmallVectorImpl<char> &OutStr) { assert(ValNo != 0 && "ValNo must be strictly positive!"); llvm::raw_svector_ostream Out(OutStr); @@ -495,9 +584,9 @@ static bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End) { /// {1:form0|[2,4]:form1|:form2} /// Polish (requires repeated form): /// {1:form0|%100=[10,20]:form2|%10=[2,4]:form1|:form2} -static void HandlePluralModifier(const DiagnosticInfo &DInfo, unsigned ValNo, +static void HandlePluralModifier(const Diagnostic &DInfo, unsigned ValNo, const char *Argument, unsigned ArgumentLen, - llvm::SmallVectorImpl<char> &OutStr) { + SmallVectorImpl<char> &OutStr) { const char *ArgumentEnd = Argument + ArgumentLen; while (1) { assert(Argument < ArgumentEnd && "Plural expression didn't match."); @@ -523,34 +612,34 @@ static void HandlePluralModifier(const DiagnosticInfo &DInfo, unsigned ValNo, /// FormatDiagnostic - Format this diagnostic into a string, substituting the /// formal arguments into the %0 slots. The result is appended onto the Str /// array. -void DiagnosticInfo:: -FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const { +void Diagnostic:: +FormatDiagnostic(SmallVectorImpl<char> &OutStr) const { if (!StoredDiagMessage.empty()) { OutStr.append(StoredDiagMessage.begin(), StoredDiagMessage.end()); return; } - llvm::StringRef Diag = + StringRef Diag = getDiags()->getDiagnosticIDs()->getDescription(getID()); FormatDiagnostic(Diag.begin(), Diag.end(), OutStr); } -void DiagnosticInfo:: +void Diagnostic:: FormatDiagnostic(const char *DiagStr, const char *DiagEnd, - llvm::SmallVectorImpl<char> &OutStr) const { + SmallVectorImpl<char> &OutStr) const { /// FormattedArgs - Keep track of all of the arguments formatted by /// ConvertArgToString and pass them into subsequent calls to /// ConvertArgToString, allowing the implementation to avoid redundancies in /// obvious cases. - llvm::SmallVector<Diagnostic::ArgumentValue, 8> FormattedArgs; + SmallVector<DiagnosticsEngine::ArgumentValue, 8> FormattedArgs; /// QualTypeVals - Pass a vector of arrays so that QualType names can be /// compared to see if more information is needed to be printed. - llvm::SmallVector<intptr_t, 2> QualTypeVals; + SmallVector<intptr_t, 2> QualTypeVals; for (unsigned i = 0, e = getNumArgs(); i < e; ++i) - if (getArgKind(i) == Diagnostic::ak_qualtype) + if (getArgKind(i) == DiagnosticsEngine::ak_qualtype) QualTypeVals.push_back(getRawArg(i)); while (DiagStr != DiagEnd) { @@ -600,17 +689,17 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, assert(isdigit(*DiagStr) && "Invalid format for argument in diagnostic"); unsigned ArgNo = *DiagStr++ - '0'; - Diagnostic::ArgumentKind Kind = getArgKind(ArgNo); + DiagnosticsEngine::ArgumentKind Kind = getArgKind(ArgNo); switch (Kind) { // ---- STRINGS ---- - case Diagnostic::ak_std_string: { + case DiagnosticsEngine::ak_std_string: { const std::string &S = getArgStdStr(ArgNo); assert(ModifierLen == 0 && "No modifiers for strings yet"); OutStr.append(S.begin(), S.end()); break; } - case Diagnostic::ak_c_string: { + case DiagnosticsEngine::ak_c_string: { const char *S = getArgCStr(ArgNo); assert(ModifierLen == 0 && "No modifiers for strings yet"); @@ -622,7 +711,7 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, break; } // ---- INTEGERS ---- - case Diagnostic::ak_sint: { + case DiagnosticsEngine::ak_sint: { int Val = getArgSInt(ArgNo); if (ModifierIs(Modifier, ModifierLen, "select")) { @@ -641,7 +730,7 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, } break; } - case Diagnostic::ak_uint: { + case DiagnosticsEngine::ak_uint: { unsigned Val = getArgUInt(ArgNo); if (ModifierIs(Modifier, ModifierLen, "select")) { @@ -660,7 +749,7 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, break; } // ---- NAMES and TYPES ---- - case Diagnostic::ak_identifierinfo: { + case DiagnosticsEngine::ak_identifierinfo: { const IdentifierInfo *II = getArgIdentifier(ArgNo); assert(ModifierLen == 0 && "No modifiers for strings yet"); @@ -674,11 +763,11 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, llvm::raw_svector_ostream(OutStr) << '\'' << II->getName() << '\''; break; } - case Diagnostic::ak_qualtype: - case Diagnostic::ak_declarationname: - case Diagnostic::ak_nameddecl: - case Diagnostic::ak_nestednamespec: - case Diagnostic::ak_declcontext: + case DiagnosticsEngine::ak_qualtype: + case DiagnosticsEngine::ak_declarationname: + case DiagnosticsEngine::ak_nameddecl: + case DiagnosticsEngine::ak_nestednamespec: + case DiagnosticsEngine::ak_declcontext: getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo), Modifier, ModifierLen, Argument, ArgumentLen, @@ -690,10 +779,10 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, // Remember this argument info for subsequent formatting operations. Turn // std::strings into a null terminated string to make it be the same case as // all the other ones. - if (Kind != Diagnostic::ak_std_string) + if (Kind != DiagnosticsEngine::ak_std_string) FormattedArgs.push_back(std::make_pair(Kind, getRawArg(ArgNo))); else - FormattedArgs.push_back(std::make_pair(Diagnostic::ak_c_string, + FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_c_string, (intptr_t)getArgStdStr(ArgNo).c_str())); } @@ -701,12 +790,12 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, StoredDiagnostic::StoredDiagnostic() { } -StoredDiagnostic::StoredDiagnostic(Diagnostic::Level Level, unsigned ID, - llvm::StringRef Message) +StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID, + StringRef Message) : ID(ID), Level(Level), Loc(), Message(Message) { } -StoredDiagnostic::StoredDiagnostic(Diagnostic::Level Level, - const DiagnosticInfo &Info) +StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, + const Diagnostic &Info) : ID(Info.getID()), Level(Level) { assert((Info.getLocation().isInvalid() || Info.hasSourceManager()) && @@ -726,13 +815,23 @@ StoredDiagnostic::StoredDiagnostic(Diagnostic::Level Level, FixIts.push_back(Info.getFixItHint(I)); } +StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID, + StringRef Message, FullSourceLoc Loc, + ArrayRef<CharSourceRange> Ranges, + ArrayRef<FixItHint> Fixits) + : ID(ID), Level(Level), Loc(Loc), Message(Message) +{ + this->Ranges.assign(Ranges.begin(), Ranges.end()); + this->FixIts.assign(FixIts.begin(), FixIts.end()); +} + StoredDiagnostic::~StoredDiagnostic() { } /// IncludeInDiagnosticCounts - This method (whose default implementation /// returns true) indicates whether the diagnostics handled by this -/// DiagnosticClient should be included in the number of diagnostics -/// reported by Diagnostic. -bool DiagnosticClient::IncludeInDiagnosticCounts() const { return true; } +/// DiagnosticConsumer should be included in the number of diagnostics +/// reported by DiagnosticsEngine. +bool DiagnosticConsumer::IncludeInDiagnosticCounts() const { return true; } PartialDiagnostic::StorageAllocator::StorageAllocator() { for (unsigned I = 0; I != NumCached; ++I) diff --git a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp index 147ba7e..9481287 100644 --- a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp @@ -21,6 +21,8 @@ #include "clang/Lex/LexDiagnostic.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/SemaDiagnostic.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ErrorHandling.h" #include <map> using namespace clang; @@ -45,6 +47,8 @@ struct StaticDiagInfoRec { unsigned Class : 3; unsigned SFINAE : 1; unsigned AccessControl : 1; + unsigned WarnNoWerror : 1; + unsigned WarnShowInSystemHeader : 1; unsigned Category : 5; uint8_t NameLen; @@ -61,21 +65,21 @@ struct StaticDiagInfoRec { const char *BriefExplanationStr; const char *FullExplanationStr; - llvm::StringRef getName() const { - return llvm::StringRef(NameStr, NameLen); + StringRef getName() const { + return StringRef(NameStr, NameLen); } - llvm::StringRef getOptionGroup() const { - return llvm::StringRef(OptionGroupStr, OptionGroupLen); + StringRef getOptionGroup() const { + return StringRef(OptionGroupStr, OptionGroupLen); } - llvm::StringRef getDescription() const { - return llvm::StringRef(DescriptionStr, DescriptionLen); + StringRef getDescription() const { + return StringRef(DescriptionStr, DescriptionLen); } - llvm::StringRef getBriefExplanation() const { - return llvm::StringRef(BriefExplanationStr, BriefExplanationLen); + StringRef getBriefExplanation() const { + return StringRef(BriefExplanationStr, BriefExplanationLen); } - llvm::StringRef getFullExplanation() const { - return llvm::StringRef(FullExplanationStr, FullExplanationLen); + StringRef getFullExplanation() const { + return StringRef(FullExplanationStr, FullExplanationLen); } bool operator<(const StaticDiagInfoRec &RHS) const { @@ -88,8 +92,8 @@ struct StaticDiagNameIndexRec { unsigned short DiagID; uint8_t NameLen; - llvm::StringRef getName() const { - return llvm::StringRef(NameStr, NameLen); + StringRef getName() const { + return StringRef(NameStr, NameLen); } bool operator<(const StaticDiagNameIndexRec &RHS) const { @@ -114,8 +118,10 @@ public: static const StaticDiagInfoRec StaticDiagInfo[] = { #define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP, \ - SFINAE,ACCESS,CATEGORY,BRIEF,FULL) \ - { diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, ACCESS, CATEGORY, \ + SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER, \ + CATEGORY,BRIEF,FULL) \ + { diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, ACCESS, \ + NOWERROR, SHOWINSYSHEADER, CATEGORY, \ STR_SIZE(#ENUM, uint8_t), STR_SIZE(GROUP, uint8_t), \ STR_SIZE(DESC, uint16_t), STR_SIZE(BRIEF, uint16_t), \ STR_SIZE(FULL, uint16_t), \ @@ -129,7 +135,7 @@ static const StaticDiagInfoRec StaticDiagInfo[] = { #include "clang/Basic/DiagnosticSemaKinds.inc" #include "clang/Basic/DiagnosticAnalysisKinds.inc" #undef DIAG - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; static const unsigned StaticDiagInfoSize = @@ -166,7 +172,8 @@ 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, 0, 0, 0, 0, 0,0,0,0 }; + StaticDiagInfoRec Find = { static_cast<unsigned short>(DiagID), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; const StaticDiagInfoRec *Found = std::lower_bound(StaticDiagInfo, StaticDiagInfo + StaticDiagInfoSize, Find); @@ -177,19 +184,36 @@ static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) { return Found; } -static unsigned GetDefaultDiagMapping(unsigned DiagID) { - if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) - return Info->Mapping; - return diag::MAP_FATAL; +static DiagnosticMappingInfo GetDefaultDiagMappingInfo(unsigned DiagID) { + DiagnosticMappingInfo Info = DiagnosticMappingInfo::Make( + diag::MAP_FATAL, /*IsUser=*/false, /*IsPragma=*/false); + + if (const StaticDiagInfoRec *StaticInfo = GetDiagInfo(DiagID)) { + Info.setMapping((diag::Mapping) StaticInfo->Mapping); + + if (StaticInfo->WarnNoWerror) { + assert(Info.getMapping() == diag::MAP_WARNING && + "Unexpected mapping with no-Werror bit!"); + Info.setNoWarningAsError(true); + } + + if (StaticInfo->WarnShowInSystemHeader) { + assert(Info.getMapping() == diag::MAP_WARNING && + "Unexpected mapping with show-in-system-header bit!"); + Info.setShowInSystemHeader(true); + } + } + + return Info; } /// getWarningOptionForDiag - Return the lowest-level warning option that /// enables the specified diagnostic. If there is no -Wfoo flag that controls /// the diagnostic, this returns null. -llvm::StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) { +StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) { if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) return Info->getOptionGroup(); - return llvm::StringRef(); + return StringRef(); } /// getCategoryNumberForDiag - Return the category number that a specified @@ -206,12 +230,28 @@ namespace { const char *NameStr; uint8_t NameLen; - llvm::StringRef getName() const { - return llvm::StringRef(NameStr, NameLen); + StringRef getName() const { + return StringRef(NameStr, NameLen); } }; } +// Unfortunately, the split between DiagnosticIDs and Diagnostic is not +// particularly clean, but for now we just implement this method here so we can +// access GetDefaultDiagMapping. +DiagnosticMappingInfo &DiagnosticsEngine::DiagState::getOrAddMappingInfo( + diag::kind Diag) +{ + std::pair<iterator, bool> Result = DiagMap.insert( + std::make_pair(Diag, DiagnosticMappingInfo())); + + // Initialize the entry if we added it. + if (Result.second) + Result.first->second = GetDefaultDiagMappingInfo(Diag); + + return Result.first->second; +} + static const StaticDiagCategoryRec CategoryNameTable[] = { #define GET_CATEGORY_TABLE #define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) }, @@ -228,9 +268,9 @@ unsigned DiagnosticIDs::getNumberOfCategories() { /// getCategoryNameFromID - Given a category ID, return the name of the /// category, an empty string if CategoryID is zero, or null if CategoryID is /// invalid. -llvm::StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) { +StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) { if (CategoryID >= getNumberOfCategories()) - return llvm::StringRef(); + return StringRef(); return CategoryNameTable[CategoryID].getName(); } @@ -256,20 +296,23 @@ DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) { } /// getName - Given a diagnostic ID, return its name -llvm::StringRef DiagnosticIDs::getName(unsigned DiagID) { +StringRef DiagnosticIDs::getName(unsigned DiagID) { if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) return Info->getName(); - return llvm::StringRef(); + return StringRef(); } /// getIdFromName - Given a diagnostic name, return its ID, or 0 -unsigned DiagnosticIDs::getIdFromName(llvm::StringRef Name) { +unsigned DiagnosticIDs::getIdFromName(StringRef Name) { const StaticDiagNameIndexRec *StaticDiagNameIndexEnd = StaticDiagNameIndex + StaticDiagNameIndexSize; if (Name.empty()) { return diag::DIAG_UPPER_LIMIT; } - StaticDiagNameIndexRec Find = { Name.data(), 0, Name.size() }; + assert(Name.size() == static_cast<uint8_t>(Name.size()) && + "Name is too long"); + StaticDiagNameIndexRec Find = { Name.data(), 0, + static_cast<uint8_t>(Name.size()) }; const StaticDiagNameIndexRec *Found = std::lower_bound( StaticDiagNameIndex, StaticDiagNameIndexEnd, Find); @@ -282,18 +325,18 @@ unsigned DiagnosticIDs::getIdFromName(llvm::StringRef Name) { /// getBriefExplanation - Given a diagnostic ID, return a brief explanation /// of the issue -llvm::StringRef DiagnosticIDs::getBriefExplanation(unsigned DiagID) { +StringRef DiagnosticIDs::getBriefExplanation(unsigned DiagID) { if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) return Info->getBriefExplanation(); - return llvm::StringRef(); + return StringRef(); } /// getFullExplanation - Given a diagnostic ID, return a full explanation /// of the issue -llvm::StringRef DiagnosticIDs::getFullExplanation(unsigned DiagID) { +StringRef DiagnosticIDs::getFullExplanation(unsigned DiagID) { if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) return Info->getFullExplanation(); - return llvm::StringRef(); + return StringRef(); } /// getBuiltinDiagClass - Return the class field of the diagnostic. @@ -305,6 +348,35 @@ static unsigned getBuiltinDiagClass(unsigned DiagID) { } //===----------------------------------------------------------------------===// +// diag_iterator +//===----------------------------------------------------------------------===// + +llvm::StringRef DiagnosticIDs::diag_iterator::getDiagName() const { + return static_cast<const StaticDiagNameIndexRec*>(impl)->getName(); +} + +unsigned DiagnosticIDs::diag_iterator::getDiagID() const { + return static_cast<const StaticDiagNameIndexRec*>(impl)->DiagID; +} + +DiagnosticIDs::diag_iterator &DiagnosticIDs::diag_iterator::operator++() { + const StaticDiagNameIndexRec* ptr = + static_cast<const StaticDiagNameIndexRec*>(impl);; + ++ptr; + impl = ptr; + return *this; +} + +DiagnosticIDs::diag_iterator DiagnosticIDs::diags_begin() { + return DiagnosticIDs::diag_iterator(StaticDiagNameIndex); +} + +DiagnosticIDs::diag_iterator DiagnosticIDs::diags_end() { + return DiagnosticIDs::diag_iterator(StaticDiagNameIndex + + StaticDiagNameIndexSize); +} + +//===----------------------------------------------------------------------===// // Custom Diagnostic information //===----------------------------------------------------------------------===// @@ -318,7 +390,7 @@ namespace clang { /// getDescription - Return the description of the specified custom /// diagnostic. - llvm::StringRef getDescription(unsigned DiagID) const { + StringRef getDescription(unsigned DiagID) const { assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() && "Invalid diagnosic ID"); return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second; @@ -331,7 +403,7 @@ namespace clang { return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first; } - unsigned getOrCreateDiagID(DiagnosticIDs::Level L, llvm::StringRef Message, + unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message, DiagnosticIDs &Diags) { DiagDesc D(L, Message); // Check to see if it already exists. @@ -366,7 +438,7 @@ DiagnosticIDs::~DiagnosticIDs() { /// 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 DiagnosticIDs::getCustomDiagID(Level L, llvm::StringRef Message) { +unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef Message) { if (CustomDiagInfo == 0) CustomDiagInfo = new diag::CustomDiagInfo(); return CustomDiagInfo->getOrCreateDiagID(L, Message, *this); @@ -400,32 +472,39 @@ bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID, getBuiltinDiagClass(DiagID) != CLASS_EXTENSION) return false; - EnabledByDefault = GetDefaultDiagMapping(DiagID) != diag::MAP_IGNORE; + EnabledByDefault = + GetDefaultDiagMappingInfo(DiagID).getMapping() != diag::MAP_IGNORE; return true; } +bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) { + if (DiagID >= diag::DIAG_UPPER_LIMIT) + return false; + + return GetDefaultDiagMappingInfo(DiagID).getMapping() == diag::MAP_ERROR; +} + /// getDescription - Given a diagnostic ID, return a description of the /// issue. -llvm::StringRef DiagnosticIDs::getDescription(unsigned DiagID) const { +StringRef DiagnosticIDs::getDescription(unsigned DiagID) const { if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) return Info->getDescription(); return CustomDiagInfo->getDescription(DiagID); } -/// getDiagnosticLevel - Based on the way the client configured the Diagnostic -/// object, classify the specified diagnostic ID into a Level, consumable by -/// the DiagnosticClient. +/// getDiagnosticLevel - Based on the way the client configured the +/// DiagnosticsEngine object, classify the specified diagnostic ID into a Level, +/// by consumable the DiagnosticClient. DiagnosticIDs::Level DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, - const Diagnostic &Diag, - diag::Mapping *mapping) const { + const DiagnosticsEngine &Diag) 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, Loc, Diag, mapping); + return getDiagnosticLevel(DiagID, DiagClass, Loc, Diag); } /// \brief Based on the way the client configured the Diagnostic @@ -437,130 +516,119 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, DiagnosticIDs::Level DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass, SourceLocation Loc, - const Diagnostic &Diag, - diag::Mapping *mapping) const { + const DiagnosticsEngine &Diag) const { // Specific non-error diagnostics may be mapped to various levels from ignored // to error. Errors can only be mapped to fatal. DiagnosticIDs::Level Result = DiagnosticIDs::Fatal; - Diagnostic::DiagStatePointsTy::iterator + DiagnosticsEngine::DiagStatePointsTy::iterator Pos = Diag.GetDiagStatePointForLoc(Loc); - Diagnostic::DiagState *State = Pos->State; - - // Get the mapping information, if unset, compute it lazily. - unsigned MappingInfo = Diag.getDiagnosticMappingInfo((diag::kind)DiagID, - State); - if (MappingInfo == 0) { - MappingInfo = GetDefaultDiagMapping(DiagID); - Diag.setDiagnosticMappingInternal(DiagID, MappingInfo, State, false, false); - } - - if (mapping) - *mapping = (diag::Mapping) (MappingInfo & 7); + DiagnosticsEngine::DiagState *State = Pos->State; - bool ShouldEmitInSystemHeader = false; + // Get the mapping information, or compute it lazily. + DiagnosticMappingInfo &MappingInfo = State->getOrAddMappingInfo( + (diag::kind)DiagID); - switch (MappingInfo & 7) { - default: assert(0 && "Unknown mapping!"); + switch (MappingInfo.getMapping()) { + default: llvm_unreachable("Unknown mapping!"); case diag::MAP_IGNORE: - // Ignore this, unless this is an extension diagnostic and we're mapping - // them onto warnings or errors. - if (!isBuiltinExtensionDiag(DiagID) || // Not an extension - Diag.ExtBehavior == Diagnostic::Ext_Ignore || // Ext ignored - (MappingInfo & 8) != 0) // User explicitly mapped it. - return DiagnosticIDs::Ignored; + Result = DiagnosticIDs::Ignored; + break; + case diag::MAP_WARNING: Result = DiagnosticIDs::Warning; - if (Diag.ExtBehavior == Diagnostic::Ext_Error) Result = DiagnosticIDs::Error; - if (Result == DiagnosticIDs::Error && Diag.ErrorsAsFatal) - Result = DiagnosticIDs::Fatal; break; case diag::MAP_ERROR: Result = DiagnosticIDs::Error; - if (Diag.ErrorsAsFatal) - Result = DiagnosticIDs::Fatal; break; 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) - return DiagnosticIDs::Ignored; + } + // Upgrade ignored diagnostics if -Weverything is enabled. + if (Diag.EnableAllWarnings && Result == DiagnosticIDs::Ignored && + !MappingInfo.isUser()) Result = DiagnosticIDs::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 (Diag.ExtBehavior == Diagnostic::Ext_Error && - (MappingInfo & 8) == 0 && - isBuiltinExtensionDiag(DiagID)) - Result = DiagnosticIDs::Error; - - if (Diag.WarningsAsErrors) - Result = DiagnosticIDs::Error; - if (Result == DiagnosticIDs::Error && Diag.ErrorsAsFatal) - Result = DiagnosticIDs::Fatal; - break; + // Ignore -pedantic diagnostics inside __extension__ blocks. + // (The diagnostics controlled by -pedantic are the extension diagnostics + // that are not enabled by default.) + bool EnabledByDefault; + bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault); + if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault) + return DiagnosticIDs::Ignored; - 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 = DiagnosticIDs::Warning; + // For extension diagnostics that haven't been explicitly mapped, check if we + // should upgrade the diagnostic. + if (IsExtensionDiag && !MappingInfo.isUser()) { + switch (Diag.ExtBehavior) { + case DiagnosticsEngine::Ext_Ignore: + break; + case DiagnosticsEngine::Ext_Warn: + // Upgrade ignored diagnostics to warnings. + if (Result == DiagnosticIDs::Ignored) + Result = DiagnosticIDs::Warning; + break; + case DiagnosticsEngine::Ext_Error: + // Upgrade ignored or warning diagnostics to errors. + if (Result == DiagnosticIDs::Ignored || Result == DiagnosticIDs::Warning) + Result = DiagnosticIDs::Error; + break; + } + } - // If warnings are globally mapped to ignore or error, do it. - if (Diag.IgnoreAllWarnings) - return DiagnosticIDs::Ignored; + // At this point, ignored errors can no longer be upgraded. + if (Result == DiagnosticIDs::Ignored) + return Result; - break; + // Honor -w, which is lower in priority than pedantic-errors, but higher than + // -Werror. + if (Result == DiagnosticIDs::Warning && Diag.IgnoreAllWarnings) + return DiagnosticIDs::Ignored; - case diag::MAP_ERROR_NO_WFATAL: - // Diagnostics specified as -Wno-fatal-error=foo should be errors, but - // unaffected by -Wfatal-errors. - Result = DiagnosticIDs::Error; - break; + // If -Werror is enabled, map warnings to errors unless explicitly disabled. + if (Result == DiagnosticIDs::Warning) { + if (Diag.WarningsAsErrors && !MappingInfo.hasNoWarningAsError()) + Result = DiagnosticIDs::Error; } - // Okay, we're about to return this as a "diagnostic to emit" one last check: - // if this is any sort of extension warning, and if we're in an __extension__ - // block, silence it. - if (Diag.AllExtensionsSilenced && isBuiltinExtensionDiag(DiagID)) - return DiagnosticIDs::Ignored; + // If -Wfatal-errors is enabled, map errors to fatal unless explicity + // disabled. + if (Result == DiagnosticIDs::Error) { + if (Diag.ErrorsAsFatal && !MappingInfo.hasNoErrorAsFatal()) + Result = DiagnosticIDs::Fatal; + } - // If we are in a system header, we ignore it. - // We also want to ignore extensions and warnings in -Werror and + // If we are in a system header, we ignore it. We look at the diagnostic class + // because 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 && + !MappingInfo.hasShowInSystemHeader() && Diag.SuppressSystemWarnings && Loc.isValid() && Diag.getSourceManager().isInSystemHeader( - Diag.getSourceManager().getInstantiationLoc(Loc))) + Diag.getSourceManager().getExpansionLoc(Loc))) return DiagnosticIDs::Ignored; return Result; } -namespace { - struct WarningOption { - // Be safe with the size of 'NameLen' because we don't statically check if - // the size will fit in the field; the struct size won't decrease with a - // shorter type anyway. - size_t NameLen; - const char *NameStr; - const short *Members; - const short *SubGroups; +struct clang::WarningOption { + // Be safe with the size of 'NameLen' because we don't statically check if + // the size will fit in the field; the struct size won't decrease with a + // shorter type anyway. + size_t NameLen; + const char *NameStr; + const short *Members; + const short *SubGroups; - llvm::StringRef getName() const { - return llvm::StringRef(NameStr, NameLen); - } - }; -} + StringRef getName() const { + return StringRef(NameStr, NameLen); + } +}; #define GET_DIAG_ARRAYS #include "clang/Basic/DiagnosticGroups.inc" @@ -580,54 +648,43 @@ static bool WarningOptionCompare(const WarningOption &LHS, return LHS.getName() < RHS.getName(); } -static void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping, - SourceLocation Loc, Diagnostic &Diag) { - // Option exists, poke all the members of its diagnostic set. +void DiagnosticIDs::getDiagnosticsInGroup( + const WarningOption *Group, + llvm::SmallVectorImpl<diag::kind> &Diags) const +{ + // Add the members of the option diagnostic set. if (const short *Member = Group->Members) { for (; *Member != -1; ++Member) - Diag.setDiagnosticMapping(*Member, Mapping, Loc); + Diags.push_back(*Member); } - // Enable/disable all subgroups along with this one. + // Add the members of the subgroups. if (const short *SubGroups = Group->SubGroups) { for (; *SubGroups != (short)-1; ++SubGroups) - MapGroupMembers(&OptionTable[(short)*SubGroups], Mapping, Loc, Diag); + getDiagnosticsInGroup(&OptionTable[(short)*SubGroups], Diags); } } -/// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g. -/// "unknown-pragmas" to have the specified mapping. This returns true and -/// ignores the request if "Group" was unknown, false otherwise. -bool DiagnosticIDs::setDiagnosticGroupMapping(llvm::StringRef Group, - diag::Mapping Map, - SourceLocation Loc, - Diagnostic &Diag) const { - assert((Loc.isValid() || - Diag.DiagStatePoints.empty() || - Diag.DiagStatePoints.back().Loc.isInvalid()) && - "Loc should be invalid only when the mapping comes from command-line"); - assert((Loc.isInvalid() || Diag.DiagStatePoints.empty() || - Diag.DiagStatePoints.back().Loc.isInvalid() || - !Diag.SourceMgr->isBeforeInTranslationUnit(Loc, - Diag.DiagStatePoints.back().Loc)) && - "Source location of new mapping is before the previous one!"); - +bool DiagnosticIDs::getDiagnosticsInGroup( + StringRef Group, + llvm::SmallVectorImpl<diag::kind> &Diags) const +{ WarningOption Key = { Group.size(), Group.data(), 0, 0 }; const WarningOption *Found = std::lower_bound(OptionTable, OptionTable + OptionTableSize, Key, WarningOptionCompare); if (Found == OptionTable + OptionTableSize || Found->getName() != Group) - return true; // Option not found. + return true; // Option not found. - MapGroupMembers(Found, Map, Loc, Diag); + getDiagnosticsInGroup(Found, Diags); return false; } /// ProcessDiag - This is the method used to report a diagnostic that is /// finally fully formed. -bool DiagnosticIDs::ProcessDiag(Diagnostic &Diag) const { - DiagnosticInfo Info(&Diag); +bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const { + Diagnostic Info(&Diag); if (Diag.SuppressAllDiagnostics) return false; @@ -665,6 +722,13 @@ bool DiagnosticIDs::ProcessDiag(Diagnostic &Diag) const { Diag.LastDiagLevel = DiagLevel; } + // Update counts for DiagnosticErrorTrap even if a fatal error occurred. + if (DiagLevel >= DiagnosticIDs::Error) { + ++Diag.TrapNumErrorsOccurred; + if (isUnrecoverable(DiagID)) + ++Diag.TrapNumUnrecoverableErrorsOccurred; + } + // If a fatal error has already been emitted, silence all subsequent // diagnostics. if (Diag.FatalErrorOccurred) { @@ -685,27 +749,26 @@ bool DiagnosticIDs::ProcessDiag(Diagnostic &Diag) const { return false; if (DiagLevel >= DiagnosticIDs::Error) { - Diag.TrapErrorOccurred = true; - if (isUnrecoverable(DiagID)) { - Diag.TrapUnrecoverableErrorOccurred = true; + if (isUnrecoverable(DiagID)) Diag.UnrecoverableErrorOccurred = true; - } if (Diag.Client->IncludeInDiagnosticCounts()) { Diag.ErrorOccurred = true; ++Diag.NumErrors; } - // If we've emitted a lot of errors, emit a fatal error after it to stop a - // flood of bogus errors. - if (Diag.ErrorLimit && Diag.NumErrors >= Diag.ErrorLimit && - DiagLevel == DiagnosticIDs::Error) + // If we've emitted a lot of errors, emit a fatal error instead of it to + // stop a flood of bogus errors. + if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit && + DiagLevel == DiagnosticIDs::Error) { Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors); + return false; + } } // If we have any Fix-Its, make sure that all of the Fix-Its point into - // source locations that aren't macro instantiations. If any point into - // macro instantiations, remove all of the Fix-Its. + // source locations that aren't macro expansions. If any point into macro + // expansions, remove all of the Fix-Its. for (unsigned I = 0, N = Diag.NumFixItHints; I != N; ++I) { const FixItHint &FixIt = Diag.FixItHints[I]; if (FixIt.RemoveRange.isInvalid() || @@ -717,7 +780,7 @@ bool DiagnosticIDs::ProcessDiag(Diagnostic &Diag) const { } // Finally, report it. - Diag.Client->HandleDiagnostic((Diagnostic::Level)DiagLevel, Info); + Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info); if (Diag.Client->IncludeInDiagnosticCounts()) { if (DiagLevel == DiagnosticIDs::Warning) ++Diag.NumWarnings; diff --git a/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp b/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp index f747c53..c1f715e 100644 --- a/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp @@ -217,25 +217,26 @@ void FileManager::removeStatCache(FileSystemStatCache *statCache) { /// \brief Retrieve the directory that the given file name resides in. /// Filename can point to either a real file or a virtual file. static const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr, - llvm::StringRef Filename) { + StringRef Filename, + bool CacheFailure) { if (Filename.empty()) return NULL; if (llvm::sys::path::is_separator(Filename[Filename.size() - 1])) return NULL; // If Filename is a directory. - llvm::StringRef DirName = llvm::sys::path::parent_path(Filename); + StringRef DirName = llvm::sys::path::parent_path(Filename); // Use the current directory if file has no path component. if (DirName.empty()) DirName = "."; - return FileMgr.getDirectory(DirName); + return FileMgr.getDirectory(DirName, CacheFailure); } /// Add all ancestors of the given path (pointing to either a file or /// a directory) as virtual directories. -void FileManager::addAncestorsAsVirtualDirs(llvm::StringRef Path) { - llvm::StringRef DirName = llvm::sys::path::parent_path(Path); +void FileManager::addAncestorsAsVirtualDirs(StringRef Path) { + StringRef DirName = llvm::sys::path::parent_path(Path); if (DirName.empty()) return; @@ -263,7 +264,8 @@ void FileManager::addAncestorsAsVirtualDirs(llvm::StringRef Path) { /// (real or virtual). This returns NULL if the directory doesn't /// exist. /// -const DirectoryEntry *FileManager::getDirectory(llvm::StringRef DirName) { +const DirectoryEntry *FileManager::getDirectory(StringRef DirName, + bool CacheFailure) { ++NumDirLookups; llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt = SeenDirEntries.GetOrCreateValue(DirName); @@ -287,6 +289,8 @@ const DirectoryEntry *FileManager::getDirectory(llvm::StringRef DirName) { struct stat StatBuf; if (getStatValue(InterndDirName, StatBuf, 0/*directory lookup*/)) { // There's no real directory at the given path. + if (!CacheFailure) + SeenDirEntries.erase(DirName); return 0; } @@ -309,7 +313,8 @@ 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, bool openFile) { +const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, + bool CacheFailure) { ++NumFileLookups; // See if there is already an entry in the map. @@ -335,10 +340,15 @@ const FileEntry *FileManager::getFile(llvm::StringRef Filename, bool openFile) { // subdirectory. This will let us avoid having to waste time on known-to-fail // searches when we go to find sys/bar.h, because all the search directories // without a 'sys' subdir will get a cached failure result. - const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename); - if (DirInfo == 0) // Directory doesn't exist, file can't exist. + const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename, + CacheFailure); + if (DirInfo == 0) { // Directory doesn't exist, file can't exist. + if (!CacheFailure) + SeenFileEntries.erase(Filename); + return 0; - + } + // FIXME: Use the directory info to prune this, before doing the stat syscall. // FIXME: This will reduce the # syscalls. @@ -347,6 +357,9 @@ const FileEntry *FileManager::getFile(llvm::StringRef Filename, bool openFile) { struct stat StatBuf; if (getStatValue(InterndFileName, StatBuf, &FileDescriptor)) { // There's no real file at the given path. + if (!CacheFailure) + SeenFileEntries.erase(Filename); + return 0; } @@ -381,7 +394,7 @@ const FileEntry *FileManager::getFile(llvm::StringRef Filename, bool openFile) { } const FileEntry * -FileManager::getVirtualFile(llvm::StringRef Filename, off_t Size, +FileManager::getVirtualFile(StringRef Filename, off_t Size, time_t ModificationTime) { ++NumFileLookups; @@ -404,7 +417,8 @@ FileManager::getVirtualFile(llvm::StringRef Filename, off_t Size, // Now that all ancestors of Filename are in the cache, the // following call is guaranteed to find the DirectoryEntry from the // cache. - const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename); + const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename, + /*CacheFailure=*/true); assert(DirInfo && "The directory of a virtual file should already be in the cache."); @@ -451,8 +465,8 @@ FileManager::getVirtualFile(llvm::StringRef Filename, off_t Size, return UFE; } -void FileManager::FixupRelativePath(llvm::SmallVectorImpl<char> &path) const { - llvm::StringRef pathRef(path.data(), path.size()); +void FileManager::FixupRelativePath(SmallVectorImpl<char> &path) const { + StringRef pathRef(path.data(), path.size()); if (FileSystemOpts.WorkingDir.empty() || llvm::sys::path::is_absolute(pathRef)) @@ -499,7 +513,7 @@ getBufferForFile(const FileEntry *Entry, std::string *ErrorStr) { } llvm::MemoryBuffer *FileManager:: -getBufferForFile(llvm::StringRef Filename, std::string *ErrorStr) { +getBufferForFile(StringRef Filename, std::string *ErrorStr) { llvm::OwningPtr<llvm::MemoryBuffer> Result; llvm::error_code ec; if (FileSystemOpts.WorkingDir.empty()) { @@ -537,7 +551,7 @@ bool FileManager::getStatValue(const char *Path, struct stat &StatBuf, StatCache.get()); } -bool FileManager::getNoncachedStatValue(llvm::StringRef Path, +bool FileManager::getNoncachedStatValue(StringRef Path, struct stat &StatBuf) { llvm::SmallString<128> FilePath(Path); FixupRelativePath(FilePath); @@ -546,7 +560,7 @@ bool FileManager::getNoncachedStatValue(llvm::StringRef Path, } void FileManager::GetUniqueIDMapping( - llvm::SmallVectorImpl<const FileEntry *> &UIDToFiles) const { + SmallVectorImpl<const FileEntry *> &UIDToFiles) const { UIDToFiles.clear(); UIDToFiles.resize(NextFileUID); @@ -558,7 +572,7 @@ void FileManager::GetUniqueIDMapping( UIDToFiles[FE->getValue()->getUID()] = FE->getValue(); // Map virtual file entries - for (llvm::SmallVector<FileEntry*, 4>::const_iterator + for (SmallVector<FileEntry*, 4>::const_iterator VFE = VirtualFileEntries.begin(), VFEEnd = VirtualFileEntries.end(); VFE != VFEEnd; ++VFE) if (*VFE && *VFE != NON_EXISTENT_FILE) diff --git a/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp index 188e2d4..38f09a0 100644 --- a/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp @@ -32,6 +32,7 @@ IdentifierInfo::IdentifierInfo() { ObjCOrBuiltinID = 0; HasMacro = false; IsExtension = false; + IsCXX11CompatKeyword = false; IsPoisoned = false; IsCPPOperatorKeyword = false; NeedsHandleIdentifier = false; @@ -55,7 +56,7 @@ namespace { class EmptyLookupIterator : public IdentifierIterator { public: - virtual llvm::StringRef Next() { return llvm::StringRef(); } + virtual StringRef Next() { return StringRef(); } }; } @@ -102,11 +103,11 @@ namespace { /// identifiers because they are language keywords. This causes the lexer to /// automatically map matching identifiers to specialized token codes. /// -/// The C90/C99/CPP/CPP0x flags are set to 2 if the token should be -/// enabled in the specified langauge, set to 1 if it is an extension -/// in the specified language, and set to 0 if disabled in the -/// specified language. -static void AddKeyword(llvm::StringRef Keyword, +/// The C90/C99/CPP/CPP0x flags are set to 3 if the token is a keyword in a +/// future language standard, set to 2 if the token should be enabled in the +/// specified langauge, set to 1 if it is an extension in the specified +/// language, and set to 0 if disabled in the specified language. +static void AddKeyword(StringRef Keyword, tok::TokenKind TokenCode, unsigned Flags, const LangOptions &LangOpts, IdentifierTable &Table) { unsigned AddResult = 0; @@ -115,7 +116,7 @@ static void AddKeyword(llvm::StringRef Keyword, else if (LangOpts.CPlusPlus0x && (Flags & KEYCXX0X)) AddResult = 2; else if (LangOpts.C99 && (Flags & KEYC99)) AddResult = 2; else if (LangOpts.GNUKeywords && (Flags & KEYGNU)) AddResult = 1; - else if (LangOpts.Microsoft && (Flags & KEYMS)) AddResult = 1; + else if (LangOpts.MicrosoftExt && (Flags & KEYMS)) AddResult = 1; else if (LangOpts.Borland && (Flags & KEYBORLAND)) AddResult = 1; else if (LangOpts.Bool && (Flags & BOOLSUPPORT)) AddResult = 2; else if (LangOpts.AltiVec && (Flags & KEYALTIVEC)) AddResult = 2; @@ -123,17 +124,20 @@ static void AddKeyword(llvm::StringRef Keyword, else if (!LangOpts.CPlusPlus && (Flags & KEYNOCXX)) AddResult = 2; else if (LangOpts.C1X && (Flags & KEYC1X)) AddResult = 2; else if (LangOpts.ObjCAutoRefCount && (Flags & KEYARC)) AddResult = 2; - + else if (LangOpts.CPlusPlus && (Flags & KEYCXX0X)) AddResult = 3; + // Don't add this keyword if disabled in this language. if (AddResult == 0) return; - IdentifierInfo &Info = Table.get(Keyword, TokenCode); + IdentifierInfo &Info = + Table.get(Keyword, AddResult == 3 ? tok::identifier : TokenCode); Info.setIsExtensionToken(AddResult == 1); + Info.setIsCXX11CompatKeyword(AddResult == 3); } /// AddCXXOperatorKeyword - Register a C++ operator keyword alternative /// representations. -static void AddCXXOperatorKeyword(llvm::StringRef Keyword, +static void AddCXXOperatorKeyword(StringRef Keyword, tok::TokenKind TokenCode, IdentifierTable &Table) { IdentifierInfo &Info = Table.get(Keyword, TokenCode); @@ -142,7 +146,7 @@ static void AddCXXOperatorKeyword(llvm::StringRef Keyword, /// AddObjCKeyword - Register an Objective-C @keyword like "class" "selector" or /// "property". -static void AddObjCKeyword(llvm::StringRef Name, +static void AddObjCKeyword(StringRef Name, tok::ObjCKeywordKind ObjCID, IdentifierTable &Table) { Table.get(Name).setObjCKeywordID(ObjCID); @@ -153,20 +157,20 @@ static void AddObjCKeyword(llvm::StringRef Name, void IdentifierTable::AddKeywords(const LangOptions &LangOpts) { // Add keywords and tokens for the current language. #define KEYWORD(NAME, FLAGS) \ - AddKeyword(llvm::StringRef(#NAME), tok::kw_ ## NAME, \ + AddKeyword(StringRef(#NAME), tok::kw_ ## NAME, \ FLAGS, LangOpts, *this); #define ALIAS(NAME, TOK, FLAGS) \ - AddKeyword(llvm::StringRef(NAME), tok::kw_ ## TOK, \ + AddKeyword(StringRef(NAME), tok::kw_ ## TOK, \ FLAGS, LangOpts, *this); #define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \ if (LangOpts.CXXOperatorNames) \ - AddCXXOperatorKeyword(llvm::StringRef(#NAME), tok::ALIAS, *this); + AddCXXOperatorKeyword(StringRef(#NAME), tok::ALIAS, *this); #define OBJC1_AT_KEYWORD(NAME) \ if (LangOpts.ObjC1) \ - AddObjCKeyword(llvm::StringRef(#NAME), tok::objc_##NAME, *this); + AddObjCKeyword(StringRef(#NAME), tok::objc_##NAME, *this); #define OBJC2_AT_KEYWORD(NAME) \ if (LangOpts.ObjC2) \ - AddObjCKeyword(llvm::StringRef(#NAME), tok::objc_##NAME, *this); + AddObjCKeyword(StringRef(#NAME), tok::objc_##NAME, *this); #define TESTING_KEYWORD(NAME, FLAGS) #include "clang/Basic/TokenKinds.def" @@ -217,6 +221,7 @@ tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const { CASE(12, 'i', 'c', include_next); CASE(16, '_', 'i', __include_macros); + CASE(16, '_', 'e', __export_macro__); #undef CASE #undef HASH } @@ -336,9 +341,9 @@ IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) const { return SI->getIdentifierInfoForSlot(argIndex); } -llvm::StringRef Selector::getNameForSlot(unsigned int argIndex) const { +StringRef Selector::getNameForSlot(unsigned int argIndex) const { IdentifierInfo *II = getIdentifierInfoForSlot(argIndex); - return II? II->getName() : llvm::StringRef(); + return II? II->getName() : StringRef(); } std::string MultiKeywordSelector::getName() const { @@ -377,7 +382,7 @@ std::string Selector::getAsString() const { /// 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) { +static bool startsWithWord(StringRef name, StringRef word) { if (name.size() < word.size()) return false; return ((name.size() == word.size() || !islower(name[word.size()])) @@ -388,10 +393,11 @@ ObjCMethodFamily Selector::getMethodFamilyImpl(Selector sel) { IdentifierInfo *first = sel.getIdentifierInfoForSlot(0); if (!first) return OMF_None; - llvm::StringRef name = first->getName(); + StringRef name = first->getName(); if (sel.isUnarySelector()) { if (name == "autorelease") return OMF_autorelease; if (name == "dealloc") return OMF_dealloc; + if (name == "finalize") return OMF_finalize; if (name == "release") return OMF_release; if (name == "retain") return OMF_retain; if (name == "retainCount") return OMF_retainCount; @@ -491,4 +497,3 @@ const char *clang::getOperatorSpelling(OverloadedOperatorKind Operator) { return 0; } - diff --git a/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp b/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp new file mode 100644 index 0000000..5f479db --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp @@ -0,0 +1,30 @@ +//===--- LangOptions.cpp - C Language Family Language Options ---*- 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 the LangOptions class. +// +//===----------------------------------------------------------------------===// +#include "clang/Basic/LangOptions.h" + +using namespace clang; + +LangOptions::LangOptions() { +#define LANGOPT(Name, Bits, Default, Description) Name = Default; +#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) set##Name(Default); +#include "clang/Basic/LangOptions.def" +} + +void LangOptions::resetNonModularOptions() { +#define LANGOPT(Name, Bits, Default, Description) +#define BENIGN_LANGOPT(Name, Bits, Default, Description) Name = Default; +#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ + Name = Default; +#include "clang/Basic/LangOptions.def" +} + diff --git a/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp b/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp index 5062d43..6e4f3e6 100644 --- a/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp @@ -23,7 +23,7 @@ using namespace clang; // PrettyStackTraceLoc //===----------------------------------------------------------------------===// -void PrettyStackTraceLoc::print(llvm::raw_ostream &OS) const { +void PrettyStackTraceLoc::print(raw_ostream &OS) const { if (Loc.isValid()) { Loc.print(OS, SM); OS << ": "; @@ -35,7 +35,7 @@ void PrettyStackTraceLoc::print(llvm::raw_ostream &OS) const { // SourceLocation //===----------------------------------------------------------------------===// -void SourceLocation::print(llvm::raw_ostream &OS, const SourceManager &SM)const{ +void SourceLocation::print(raw_ostream &OS, const SourceManager &SM)const{ if (!isValid()) { OS << "<invalid loc>"; return; @@ -48,13 +48,13 @@ void SourceLocation::print(llvm::raw_ostream &OS, const SourceManager &SM)const{ OS << "<invalid>"; return; } - // The instantiation and spelling pos is identical for file locs. + // The macro expansion and spelling pos is identical for file locs. OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':' << PLoc.getColumn(); return; } - SM.getInstantiationLoc(*this).print(OS, SM); + SM.getExpansionLoc(*this).print(OS, SM); OS << " <Spelling="; SM.getSpellingLoc(*this).print(OS, SM); @@ -75,9 +75,9 @@ FileID FullSourceLoc::getFileID() const { } -FullSourceLoc FullSourceLoc::getInstantiationLoc() const { +FullSourceLoc FullSourceLoc::getExpansionLoc() const { assert(isValid()); - return FullSourceLoc(SrcMgr->getInstantiationLoc(*this), *SrcMgr); + return FullSourceLoc(SrcMgr->getExpansionLoc(*this), *SrcMgr); } FullSourceLoc FullSourceLoc::getSpellingLoc() const { @@ -85,14 +85,14 @@ FullSourceLoc FullSourceLoc::getSpellingLoc() const { return FullSourceLoc(SrcMgr->getSpellingLoc(*this), *SrcMgr); } -unsigned FullSourceLoc::getInstantiationLineNumber(bool *Invalid) const { +unsigned FullSourceLoc::getExpansionLineNumber(bool *Invalid) const { assert(isValid()); - return SrcMgr->getInstantiationLineNumber(*this, Invalid); + return SrcMgr->getExpansionLineNumber(*this, Invalid); } -unsigned FullSourceLoc::getInstantiationColumnNumber(bool *Invalid) const { +unsigned FullSourceLoc::getExpansionColumnNumber(bool *Invalid) const { assert(isValid()); - return SrcMgr->getInstantiationColumnNumber(*this, Invalid); + return SrcMgr->getExpansionColumnNumber(*this, Invalid); } unsigned FullSourceLoc::getSpellingLineNumber(bool *Invalid) const { @@ -125,7 +125,7 @@ const llvm::MemoryBuffer* FullSourceLoc::getBuffer(bool *Invalid) const { return SrcMgr->getBuffer(SrcMgr->getFileID(*this), Invalid); } -llvm::StringRef FullSourceLoc::getBufferData(bool *Invalid) const { +StringRef FullSourceLoc::getBufferData(bool *Invalid) const { return getBuffer(Invalid)->getBuffer(); } diff --git a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp index 45922c1..364663e 100644 --- a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp @@ -17,10 +17,12 @@ #include "clang/Basic/FileManager.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Capacity.h" #include <algorithm> #include <string> #include <cstring> @@ -39,9 +41,8 @@ ContentCache::~ContentCache() { delete Buffer.getPointer(); } -/// getSizeBytesMapped - Returns the number of bytes actually mapped for -/// this ContentCache. This can be 0 if the MemBuffer was not actually -/// instantiated. +/// getSizeBytesMapped - Returns the number of bytes actually mapped for this +/// ContentCache. This can be 0 if the MemBuffer was not actually expanded. unsigned ContentCache::getSizeBytesMapped() const { return Buffer.getPointer() ? Buffer.getPointer()->getBufferSize() : 0; } @@ -78,7 +79,7 @@ void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B, Buffer.setInt(DoNotFree? DoNotFreeFlag : 0); } -const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag, +const llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag, const SourceManager &SM, SourceLocation Loc, bool *Invalid) const { @@ -105,7 +106,7 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag, // that we are in an inconsistent situation and error out as quickly as // possible. if (!Buffer.getPointer()) { - const llvm::StringRef FillStr("<<<MISSING SOURCE FILE>>>\n"); + const StringRef FillStr("<<<MISSING SOURCE FILE>>>\n"); Buffer.setPointer(MemoryBuffer::getNewMemBuffer(ContentsEntry->getSize(), "<invalid>")); char *Ptr = const_cast<char*>(Buffer.getPointer()->getBufferStart()); @@ -143,7 +144,7 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag, // If the buffer is valid, check to see if it has a UTF Byte Order Mark // (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(); + StringRef BufStr = Buffer.getPointer()->getBuffer(); const char *InvalidBOM = llvm::StringSwitch<const char *>(BufStr) .StartsWith("\xFE\xFF", "UTF-16 (BE)") .StartsWith("\xFF\xFE", "UTF-16 (LE)") @@ -169,7 +170,7 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag, return Buffer.getPointer(); } -unsigned LineTableInfo::getLineTableFilenameID(llvm::StringRef Name) { +unsigned LineTableInfo::getLineTableFilenameID(StringRef Name) { // Look up the filename in the string table, returning the pre-existing value // if it exists. llvm::StringMapEntry<unsigned> &Entry = @@ -186,7 +187,7 @@ unsigned LineTableInfo::getLineTableFilenameID(llvm::StringRef Name) { /// AddLineNote - Add a line note to the line table that indicates that there /// is a #line at the specified FID/Offset location which changes the presumed /// location to LineNo/FilenameID. -void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset, +void LineTableInfo::AddLineNote(int FID, unsigned Offset, unsigned LineNo, int FilenameID) { std::vector<LineEntry> &Entries = LineEntries[FID]; @@ -217,7 +218,7 @@ void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset, /// presumed #include stack. If it is 1, this is a file entry, if it is 2 then /// this is a file exit. FileKind specifies whether this is a system header or /// extern C system header. -void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset, +void LineTableInfo::AddLineNote(int FID, unsigned Offset, unsigned LineNo, int FilenameID, unsigned EntryExit, SrcMgr::CharacteristicKind FileKind) { @@ -251,7 +252,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(int FID, unsigned Offset) { const std::vector<LineEntry> &Entries = LineEntries[FID]; assert(!Entries.empty() && "No #line entries for this FID after all!"); @@ -270,14 +271,14 @@ 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(int FID, const std::vector<LineEntry> &Entries) { LineEntries[FID] = Entries; } /// getLineTableFilenameID - Return the uniqued ID for the specified filename. /// -unsigned SourceManager::getLineTableFilenameID(llvm::StringRef Name) { +unsigned SourceManager::getLineTableFilenameID(StringRef Name) { if (LineTable == 0) LineTable = new LineTableInfo(); return LineTable->getLineTableFilenameID(Name); @@ -289,7 +290,7 @@ unsigned SourceManager::getLineTableFilenameID(llvm::StringRef Name) { /// unspecified. void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID) { - std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc); + std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); bool Invalid = false; const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid); @@ -319,7 +320,7 @@ void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo, return AddLineNote(Loc, LineNo, FilenameID); } - std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc); + std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); bool Invalid = false; const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid); @@ -362,7 +363,7 @@ LineTableInfo &SourceManager::getLineTable() { // Private 'Create' methods. //===----------------------------------------------------------------------===// -SourceManager::SourceManager(Diagnostic &Diag, FileManager &FileMgr) +SourceManager::SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr) : Diag(Diag), FileMgr(FileMgr), OverridenFilesKeepOriginalName(true), ExternalSLocEntries(0), LineTable(0), NumLinearScans(0), NumBinaryProbes(0), FakeBufferForRecovery(0) { @@ -387,11 +388,18 @@ SourceManager::~SourceManager() { } delete FakeBufferForRecovery; + + for (llvm::DenseMap<FileID, MacroArgsMap *>::iterator + I = MacroArgsCacheMap.begin(),E = MacroArgsCacheMap.end(); I!=E; ++I) { + delete I->second; + } } void SourceManager::clearIDTables() { MainFileID = FileID(); - SLocEntryTable.clear(); + LocalSLocEntryTable.clear(); + LoadedSLocEntryTable.clear(); + SLocEntryLoaded.clear(); LastLineNoFileIDQuery = FileID(); LastLineNoContentCache = 0; LastFileIDLookup = FileID(); @@ -399,9 +407,10 @@ void SourceManager::clearIDTables() { if (LineTable) LineTable->clear(); - // Use up FileID #0 as an invalid instantiation. - NextOffset = 0; - createInstantiationLoc(SourceLocation(),SourceLocation(),SourceLocation(), 1); + // Use up FileID #0 as an invalid expansion. + NextLocalOffset = 0; + CurrentLoadedOffset = MaxLoadedOffset; + createExpansionLoc(SourceLocation(),SourceLocation(),SourceLocation(), 1); } /// getOrCreateContentCache - Create or return a cached ContentCache for the @@ -452,33 +461,16 @@ SourceManager::createMemBufferContentCache(const MemoryBuffer *Buffer) { return Entry; } -void SourceManager::PreallocateSLocEntries(ExternalSLocEntrySource *Source, - unsigned NumSLocEntries, - unsigned NextOffset) { - ExternalSLocEntries = Source; - this->NextOffset = NextOffset; - unsigned CurPrealloc = SLocEntryLoaded.size(); - // If we've ever preallocated, we must not count the dummy entry. - if (CurPrealloc) --CurPrealloc; - SLocEntryLoaded.resize(NumSLocEntries + 1); - SLocEntryLoaded[0] = true; - SLocEntryTable.resize(SLocEntryTable.size() + NumSLocEntries - CurPrealloc); -} - -void SourceManager::ClearPreallocatedSLocEntries() { - unsigned I = 0; - for (unsigned N = SLocEntryLoaded.size(); I != N; ++I) - if (!SLocEntryLoaded[I]) - break; - - // We've already loaded all preallocated source location entries. - if (I == SLocEntryLoaded.size()) - return; - - // Remove everything from location I onward. - SLocEntryTable.resize(I); - SLocEntryLoaded.clear(); - ExternalSLocEntries = 0; +std::pair<int, unsigned> +SourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries, + unsigned TotalSize) { + assert(ExternalSLocEntries && "Don't have an external sloc source"); + LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries); + SLocEntryLoaded.resize(LoadedSLocEntryTable.size()); + CurrentLoadedOffset -= TotalSize; + assert(CurrentLoadedOffset >= NextLocalOffset && "Out of source locations"); + int ID = LoadedSLocEntryTable.size(); + return std::make_pair(-ID - 1, CurrentLoadedOffset); } /// \brief As part of recovering from missing or changed content, produce a @@ -492,7 +484,7 @@ const llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const { } //===----------------------------------------------------------------------===// -// Methods to create new FileID's and instantiations. +// Methods to create new FileID's and macro expansions. //===----------------------------------------------------------------------===// /// createFileID - Create a new FileID for the specified ContentCache and @@ -501,77 +493,76 @@ const llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const { FileID SourceManager::createFileID(const ContentCache *File, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, - unsigned PreallocatedID, - unsigned Offset) { - if (PreallocatedID) { - // If we're filling in a preallocated ID, just load in the file - // entry and return. - assert(PreallocatedID < SLocEntryLoaded.size() && - "Preallocate ID out-of-range"); - assert(!SLocEntryLoaded[PreallocatedID] && - "Source location entry already loaded"); - assert(Offset && "Preallocate source location cannot have zero offset"); - SLocEntryTable[PreallocatedID] - = SLocEntry::get(Offset, FileInfo::get(IncludePos, File, FileCharacter)); - SLocEntryLoaded[PreallocatedID] = true; - FileID FID = FileID::get(PreallocatedID); - return FID; + int LoadedID, unsigned LoadedOffset) { + if (LoadedID < 0) { + assert(LoadedID != -1 && "Loading sentinel FileID"); + unsigned Index = unsigned(-LoadedID) - 2; + assert(Index < LoadedSLocEntryTable.size() && "FileID out of range"); + assert(!SLocEntryLoaded[Index] && "FileID already loaded"); + LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset, + FileInfo::get(IncludePos, File, FileCharacter)); + SLocEntryLoaded[Index] = true; + return FileID::get(LoadedID); } - - SLocEntryTable.push_back(SLocEntry::get(NextOffset, - FileInfo::get(IncludePos, File, - FileCharacter))); + LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, + FileInfo::get(IncludePos, File, + FileCharacter))); unsigned FileSize = File->getSize(); - assert(NextOffset+FileSize+1 > NextOffset && "Ran out of source locations!"); - NextOffset += FileSize+1; + assert(NextLocalOffset + FileSize + 1 > NextLocalOffset && + NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset && + "Ran out of source locations!"); + // We do a +1 here because we want a SourceLocation that means "the end of the + // file", e.g. for the "no newline at the end of the file" diagnostic. + NextLocalOffset += 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); + FileID FID = FileID::get(LocalSLocEntryTable.size()-1); return LastFileIDLookup = FID; } SourceLocation -SourceManager::createMacroArgInstantiationLoc(SourceLocation SpellingLoc, - SourceLocation ILoc, - unsigned TokLength) { - InstantiationInfo II = - InstantiationInfo::createForMacroArg(SpellingLoc, ILoc); - return createInstantiationLocImpl(II, TokLength); -} - -SourceLocation SourceManager::createInstantiationLoc(SourceLocation SpellingLoc, - SourceLocation ILocStart, - SourceLocation ILocEnd, - unsigned TokLength, - unsigned PreallocatedID, - unsigned Offset) { - InstantiationInfo II = - InstantiationInfo::create(SpellingLoc, ILocStart, ILocEnd); - return createInstantiationLocImpl(II, TokLength, PreallocatedID, Offset); +SourceManager::createMacroArgExpansionLoc(SourceLocation SpellingLoc, + SourceLocation ExpansionLoc, + unsigned TokLength) { + ExpansionInfo Info = ExpansionInfo::createForMacroArg(SpellingLoc, + ExpansionLoc); + return createExpansionLocImpl(Info, TokLength); } SourceLocation -SourceManager::createInstantiationLocImpl(const InstantiationInfo &II, - unsigned TokLength, - unsigned PreallocatedID, - unsigned Offset) { - if (PreallocatedID) { - // If we're filling in a preallocated ID, just load in the - // instantiation entry and return. - assert(PreallocatedID < SLocEntryLoaded.size() && - "Preallocate ID out-of-range"); - assert(!SLocEntryLoaded[PreallocatedID] && - "Source location entry already loaded"); - assert(Offset && "Preallocate source location cannot have zero offset"); - SLocEntryTable[PreallocatedID] = SLocEntry::get(Offset, II); - SLocEntryLoaded[PreallocatedID] = true; - return SourceLocation::getMacroLoc(Offset); +SourceManager::createExpansionLoc(SourceLocation SpellingLoc, + SourceLocation ExpansionLocStart, + SourceLocation ExpansionLocEnd, + unsigned TokLength, + int LoadedID, + unsigned LoadedOffset) { + ExpansionInfo Info = ExpansionInfo::create(SpellingLoc, ExpansionLocStart, + ExpansionLocEnd); + return createExpansionLocImpl(Info, TokLength, LoadedID, LoadedOffset); +} + +SourceLocation +SourceManager::createExpansionLocImpl(const ExpansionInfo &Info, + unsigned TokLength, + int LoadedID, + unsigned LoadedOffset) { + if (LoadedID < 0) { + assert(LoadedID != -1 && "Loading sentinel FileID"); + unsigned Index = unsigned(-LoadedID) - 2; + assert(Index < LoadedSLocEntryTable.size() && "FileID out of range"); + assert(!SLocEntryLoaded[Index] && "FileID already loaded"); + LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset, Info); + SLocEntryLoaded[Index] = true; + return SourceLocation::getMacroLoc(LoadedOffset); } - SLocEntryTable.push_back(SLocEntry::get(NextOffset, II)); - assert(NextOffset+TokLength+1 > NextOffset && "Ran out of source locations!"); - NextOffset += TokLength+1; - return SourceLocation::getMacroLoc(NextOffset-(TokLength+1)); + LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info)); + assert(NextLocalOffset + TokLength + 1 > NextLocalOffset && + NextLocalOffset + TokLength + 1 <= CurrentLoadedOffset && + "Ran out of source locations!"); + // See createFileID for that +1. + NextLocalOffset += TokLength + 1; + return SourceLocation::getMacroLoc(NextLocalOffset - (TokLength + 1)); } const llvm::MemoryBuffer * @@ -602,9 +593,9 @@ void SourceManager::overrideFileContents(const FileEntry *SourceFile, OverriddenFiles[SourceFile] = NewFile; } -llvm::StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const { +StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const { bool MyInvalid = false; - const SLocEntry &SLoc = getSLocEntry(FID.ID, &MyInvalid); + const SLocEntry &SLoc = getSLocEntry(FID, &MyInvalid); if (!SLoc.isFile() || MyInvalid) { if (Invalid) *Invalid = true; @@ -627,18 +618,32 @@ llvm::StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const { // SourceLocation manipulation methods. //===----------------------------------------------------------------------===// -/// getFileIDSlow - Return the FileID for a SourceLocation. This is a very hot -/// method that is used for all SourceManager queries that start with a -/// SourceLocation object. It is responsible for finding the entry in -/// SLocEntryTable which contains the specified location. +/// \brief Return the FileID for a SourceLocation. /// +/// This is the cache-miss path of getFileID. Not as hot as that function, but +/// still very important. It is responsible for finding the entry in the +/// SLocEntry tables that contains the specified location. FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { if (!SLocOffset) return FileID::get(0); + // Now it is time to search for the correct file. See where the SLocOffset + // sits in the global view and consult local or loaded buffers for it. + if (SLocOffset < NextLocalOffset) + return getFileIDLocal(SLocOffset); + return getFileIDLoaded(SLocOffset); +} + +/// \brief Return the FileID for a SourceLocation with a low offset. +/// +/// This function knows that the SourceLocation is in a local buffer, not a +/// loaded one. +FileID SourceManager::getFileIDLocal(unsigned SLocOffset) const { + assert(SLocOffset < NextLocalOffset && "Bad function choice"); + // 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 + // behavior: 1) a lot of searched FileID's are "near" the cached file + // location or are "near" the cached expansion location. 2) others are just // completely random and may be a very long way away. // // To handle this, we do a linear search for up to 8 steps to catch #1 quickly @@ -649,12 +654,13 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { // most newly created FileID. std::vector<SrcMgr::SLocEntry>::const_iterator I; - if (SLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset) { + if (LastFileIDLookup.ID < 0 || + LocalSLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset) { // Neither loc prunes our search. - I = SLocEntryTable.end(); + I = LocalSLocEntryTable.end(); } else { // Perhaps it is near the file point. - I = SLocEntryTable.begin()+LastFileIDLookup.ID; + I = LocalSLocEntryTable.begin()+LastFileIDLookup.ID; } // Find the FileID that contains this. "I" is an iterator that points to a @@ -662,25 +668,12 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { unsigned NumProbes = 0; while (1) { --I; - 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, - I-SLocEntryTable.begin(), - I->isInstantiation() ? "inst" : "file", - LastFileIDLookup.ID, int(SLocEntryTable.end()-I)); -#endif - FileID Res = FileID::get(I-SLocEntryTable.begin()); - - // If this isn't an instantiation, remember it. We have good locality - // across FileID lookups. - if (!I->isInstantiation()) + FileID Res = FileID::get(int(I - LocalSLocEntryTable.begin())); + + // If this isn't an expansion, remember it. We have good locality across + // FileID lookups. + if (!I->isExpansion()) LastFileIDLookup = Res; NumLinearScans += NumProbes+1; return Res; @@ -691,7 +684,7 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { // 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(); + unsigned GreaterIndex = I - LocalSLocEntryTable.begin(); // LessIndex - This is the lower bound of the range that we're searching. // We know that the offset corresponding to the FileID is is less than // SLocOffset. @@ -700,8 +693,7 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { while (1) { bool Invalid = false; unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex; - unsigned MidOffset = getSLocEntry(FileID::get(MiddleIndex), &Invalid) - .getOffset(); + unsigned MidOffset = getLocalSLocEntry(MiddleIndex, &Invalid).getOffset(); if (Invalid) return FileID::get(0); @@ -715,18 +707,14 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { } // If the middle index contains the value, succeed and return. + // FIXME: This could be made faster by using a function that's aware of + // being in the local area. if (isOffsetInFileID(FileID::get(MiddleIndex), SLocOffset)) { -#if 0 - printf("bin %d -> %d [%s] %d %d\n", SLocOffset, - I-SLocEntryTable.begin(), - I->isInstantiation() ? "inst" : "file", - LastFileIDLookup.ID, int(SLocEntryTable.end()-I)); -#endif FileID Res = FileID::get(MiddleIndex); - // If this isn't an instantiation, remember it. We have good locality + // If this isn't a macro expansion, remember it. We have good locality // across FileID lookups. - if (!I->isInstantiation()) + if (!LocalSLocEntryTable[MiddleIndex].isExpansion()) LastFileIDLookup = Res; NumBinaryProbes += NumProbes; return Res; @@ -737,17 +725,82 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { } } +/// \brief Return the FileID for a SourceLocation with a high offset. +/// +/// This function knows that the SourceLocation is in a loaded buffer, not a +/// local one. +FileID SourceManager::getFileIDLoaded(unsigned SLocOffset) const { + assert(SLocOffset >= CurrentLoadedOffset && "Bad function choice"); + + // Sanity checking, otherwise a bug may lead to hanging in release build. + if (SLocOffset < CurrentLoadedOffset) + return FileID(); + + // Essentially the same as the local case, but the loaded array is sorted + // in the other direction. + + // First do a linear scan from the last lookup position, if possible. + unsigned I; + int LastID = LastFileIDLookup.ID; + if (LastID >= 0 || getLoadedSLocEntryByID(LastID).getOffset() < SLocOffset) + I = 0; + else + I = (-LastID - 2) + 1; + + unsigned NumProbes; + for (NumProbes = 0; NumProbes < 8; ++NumProbes, ++I) { + // Make sure the entry is loaded! + const SrcMgr::SLocEntry &E = getLoadedSLocEntry(I); + if (E.getOffset() <= SLocOffset) { + FileID Res = FileID::get(-int(I) - 2); + + if (!E.isExpansion()) + LastFileIDLookup = Res; + NumLinearScans += NumProbes + 1; + return Res; + } + } + + // Linear scan failed. Do the binary search. Note the reverse sorting of the + // table: GreaterIndex is the one where the offset is greater, which is + // actually a lower index! + unsigned GreaterIndex = I; + unsigned LessIndex = LoadedSLocEntryTable.size(); + NumProbes = 0; + while (1) { + ++NumProbes; + unsigned MiddleIndex = (LessIndex - GreaterIndex) / 2 + GreaterIndex; + const SrcMgr::SLocEntry &E = getLoadedSLocEntry(MiddleIndex); + + ++NumProbes; + + if (E.getOffset() > SLocOffset) { + GreaterIndex = MiddleIndex; + continue; + } + + if (isOffsetInFileID(FileID::get(-int(MiddleIndex) - 2), SLocOffset)) { + FileID Res = FileID::get(-int(MiddleIndex) - 2); + if (!E.isExpansion()) + LastFileIDLookup = Res; + NumBinaryProbes += NumProbes; + return Res; + } + + LessIndex = MiddleIndex; + } +} + SourceLocation SourceManager:: -getInstantiationLocSlowCase(SourceLocation Loc) const { +getExpansionLocSlowCase(SourceLocation Loc) const { do { // Note: If Loc indicates an offset into a token that came from a macro // expansion (e.g. the 5th character of the token) we do not want to add - // this offset when going to the instantiation location. The instatiation + // this offset when going to the expansion location. The expansion // location is the macro invocation, which the offset has nothing to do // with. This is unlike when we get the spelling loc, because the offset // directly correspond to the token whose spelling we're inspecting. - Loc = getSLocEntry(getFileID(Loc)).getInstantiation() - .getInstantiationLocStart(); + Loc = getSLocEntry(getFileID(Loc)).getExpansion().getExpansionLocStart(); } while (!Loc.isFileID()); return Loc; @@ -756,23 +809,32 @@ getInstantiationLocSlowCase(SourceLocation Loc) const { SourceLocation SourceManager::getSpellingLocSlowCase(SourceLocation Loc) const { do { std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc); - Loc = getSLocEntry(LocInfo.first).getInstantiation().getSpellingLoc(); - Loc = Loc.getFileLocWithOffset(LocInfo.second); + Loc = getSLocEntry(LocInfo.first).getExpansion().getSpellingLoc(); + Loc = Loc.getLocWithOffset(LocInfo.second); + } while (!Loc.isFileID()); + return Loc; +} + +SourceLocation SourceManager::getFileLocSlowCase(SourceLocation Loc) const { + do { + if (isMacroArgExpansion(Loc)) + Loc = getImmediateSpellingLoc(Loc); + else + Loc = getImmediateExpansionRange(Loc).first; } while (!Loc.isFileID()); return Loc; } std::pair<FileID, unsigned> -SourceManager::getDecomposedInstantiationLocSlowCase( +SourceManager::getDecomposedExpansionLocSlowCase( const SrcMgr::SLocEntry *E) const { - // If this is an instantiation record, walk through all the instantiation - // points. + // If this is an expansion record, walk through all the expansion points. FileID FID; SourceLocation Loc; unsigned Offset; do { - Loc = E->getInstantiation().getInstantiationLocStart(); + Loc = E->getExpansion().getExpansionLocStart(); FID = getFileID(Loc); E = &getSLocEntry(FID); @@ -785,16 +847,16 @@ SourceManager::getDecomposedInstantiationLocSlowCase( std::pair<FileID, unsigned> SourceManager::getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E, unsigned Offset) const { - // If this is an instantiation record, walk through all the instantiation - // points. + // If this is an expansion record, walk through all the expansion points. FileID FID; SourceLocation Loc; do { - Loc = E->getInstantiation().getSpellingLoc(); + Loc = E->getExpansion().getSpellingLoc(); + Loc = Loc.getLocWithOffset(Offset); FID = getFileID(Loc); E = &getSLocEntry(FID); - Offset += Loc.getOffset()-E->getOffset(); + Offset = Loc.getOffset()-E->getOffset(); } while (!Loc.isFileID()); return std::make_pair(FID, Offset); @@ -807,45 +869,45 @@ SourceManager::getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E, SourceLocation SourceManager::getImmediateSpellingLoc(SourceLocation Loc) const{ if (Loc.isFileID()) return Loc; std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc); - Loc = getSLocEntry(LocInfo.first).getInstantiation().getSpellingLoc(); - return Loc.getFileLocWithOffset(LocInfo.second); + Loc = getSLocEntry(LocInfo.first).getExpansion().getSpellingLoc(); + return Loc.getLocWithOffset(LocInfo.second); } -/// getImmediateInstantiationRange - Loc is required to be an instantiation -/// location. Return the start/end of the instantiation information. +/// getImmediateExpansionRange - Loc is required to be an expansion location. +/// Return the start/end of the expansion information. std::pair<SourceLocation,SourceLocation> -SourceManager::getImmediateInstantiationRange(SourceLocation Loc) const { - assert(Loc.isMacroID() && "Not an instantiation loc!"); - const InstantiationInfo &II = getSLocEntry(getFileID(Loc)).getInstantiation(); - return II.getInstantiationLocRange(); +SourceManager::getImmediateExpansionRange(SourceLocation Loc) const { + assert(Loc.isMacroID() && "Not a macro expansion loc!"); + const ExpansionInfo &Expansion = getSLocEntry(getFileID(Loc)).getExpansion(); + return Expansion.getExpansionLocRange(); } -/// getInstantiationRange - Given a SourceLocation object, return the -/// range of tokens covered by the instantiation in the ultimate file. +/// getExpansionRange - Given a SourceLocation object, return the range of +/// tokens covered by the expansion in the ultimate file. std::pair<SourceLocation,SourceLocation> -SourceManager::getInstantiationRange(SourceLocation Loc) const { +SourceManager::getExpansionRange(SourceLocation Loc) const { if (Loc.isFileID()) return std::make_pair(Loc, Loc); std::pair<SourceLocation,SourceLocation> Res = - getImmediateInstantiationRange(Loc); + getImmediateExpansionRange(Loc); - // Fully resolve the start and end locations to their ultimate instantiation + // Fully resolve the start and end locations to their ultimate expansion // points. while (!Res.first.isFileID()) - Res.first = getImmediateInstantiationRange(Res.first).first; + Res.first = getImmediateExpansionRange(Res.first).first; while (!Res.second.isFileID()) - Res.second = getImmediateInstantiationRange(Res.second).second; + Res.second = getImmediateExpansionRange(Res.second).second; return Res; } -bool SourceManager::isMacroArgInstantiation(SourceLocation Loc) const { +bool SourceManager::isMacroArgExpansion(SourceLocation Loc) const { if (!Loc.isMacroID()) return false; FileID FID = getFileID(Loc); const SrcMgr::SLocEntry *E = &getSLocEntry(FID); - const SrcMgr::InstantiationInfo &II = E->getInstantiation(); - return II.isMacroArgInstantiation(); + const SrcMgr::ExpansionInfo &Expansion = E->getExpansion(); + return Expansion.isMacroArgExpansion(); } @@ -913,10 +975,10 @@ unsigned SourceManager::getSpellingColumnNumber(SourceLocation Loc, return getColumnNumber(LocInfo.first, LocInfo.second, Invalid); } -unsigned SourceManager::getInstantiationColumnNumber(SourceLocation Loc, - bool *Invalid) const { +unsigned SourceManager::getExpansionColumnNumber(SourceLocation Loc, + bool *Invalid) const { if (isInvalid(Loc, Invalid)) return 0; - std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc); + std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); return getColumnNumber(LocInfo.first, LocInfo.second, Invalid); } @@ -927,10 +989,10 @@ unsigned SourceManager::getPresumedColumnNumber(SourceLocation Loc, } static LLVM_ATTRIBUTE_NOINLINE void -ComputeLineNumbers(Diagnostic &Diag, ContentCache *FI, +ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI, llvm::BumpPtrAllocator &Alloc, const SourceManager &SM, bool &Invalid); -static void ComputeLineNumbers(Diagnostic &Diag, ContentCache *FI, +static void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI, llvm::BumpPtrAllocator &Alloc, const SourceManager &SM, bool &Invalid) { // Note that calling 'getBuffer()' may lazily page in the file. @@ -941,7 +1003,7 @@ static void ComputeLineNumbers(Diagnostic &Diag, ContentCache *FI, // Find the file offsets of all of the *physical* source lines. This does // not look at trigraphs, escaped newlines, or anything else tricky. - llvm::SmallVector<unsigned, 256> LineOffsets; + SmallVector<unsigned, 256> LineOffsets; // Line #1 starts at char 0. LineOffsets.push_back(0); @@ -1108,10 +1170,10 @@ unsigned SourceManager::getSpellingLineNumber(SourceLocation Loc, std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc); return getLineNumber(LocInfo.first, LocInfo.second); } -unsigned SourceManager::getInstantiationLineNumber(SourceLocation Loc, - bool *Invalid) const { +unsigned SourceManager::getExpansionLineNumber(SourceLocation Loc, + bool *Invalid) const { if (isInvalid(Loc, Invalid)) return 0; - std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc); + std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); return getLineNumber(LocInfo.first, LocInfo.second); } unsigned SourceManager::getPresumedLineNumber(SourceLocation Loc, @@ -1131,7 +1193,7 @@ unsigned SourceManager::getPresumedLineNumber(SourceLocation Loc, 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); + std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); bool Invalid = false; const SLocEntry &SEntry = getSLocEntry(LocInfo.first, &Invalid); if (Invalid || !SEntry.isFile()) @@ -1172,13 +1234,13 @@ const char *SourceManager::getBufferName(SourceLocation Loc, /// or GNU line marker directives. This provides a view on the data that a /// user should see in diagnostics, for example. /// -/// Note that a presumed location is always given as the instantiation point -/// of an instantiation location, not at the spelling location. +/// Note that a presumed location is always given as the expansion point of an +/// expansion 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); + // Presumed locations are always for expansion points. + std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); bool Invalid = false; const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid); @@ -1229,7 +1291,7 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const { // Handle virtual #include manipulation. if (Entry->IncludeOffset) { IncludeLoc = getLocForStartOfFile(LocInfo.first); - IncludeLoc = IncludeLoc.getFileLocWithOffset(Entry->IncludeOffset); + IncludeLoc = IncludeLoc.getLocWithOffset(Entry->IncludeOffset); } } } @@ -1237,6 +1299,25 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const { return PresumedLoc(Filename, LineNo, ColNo, IncludeLoc); } +/// \brief The size of the SLocEnty that \arg FID represents. +unsigned SourceManager::getFileIDSize(FileID FID) const { + bool Invalid = false; + const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); + if (Invalid) + return 0; + + int ID = FID.ID; + unsigned NextOffset; + if ((ID > 0 && unsigned(ID+1) == local_sloc_entry_size())) + NextOffset = getNextLocalOffset(); + else if (ID+1 == -1) + NextOffset = MaxLoadedOffset; + else + NextOffset = getSLocEntry(FileID::get(ID+1)).getOffset(); + + return NextOffset - Entry.getOffset() - 1; +} + //===----------------------------------------------------------------------===// // Other miscellaneous methods. //===----------------------------------------------------------------------===// @@ -1259,24 +1340,36 @@ static llvm::Optional<ino_t> getActualFileInode(const FileEntry *File) { /// \brief Get the source location for the given file:line:col triplet. /// /// If the source file is included multiple times, the source location will -/// be based upon the first inclusion. -SourceLocation SourceManager::getLocation(const FileEntry *SourceFile, - unsigned Line, unsigned Col) { +/// be based upon an arbitrary inclusion. +SourceLocation SourceManager::translateFileLineCol(const FileEntry *SourceFile, + unsigned Line, + unsigned Col) const { assert(SourceFile && "Null source file!"); assert(Line && Col && "Line and column should start from 1!"); + FileID FirstFID = translateFile(SourceFile); + return translateLineCol(FirstFID, Line, Col); +} + +/// \brief Get the FileID for the given file. +/// +/// If the source file is included multiple times, the FileID will be the +/// first inclusion. +FileID SourceManager::translateFile(const FileEntry *SourceFile) const { + assert(SourceFile && "Null source file!"); + // Find the first file ID that corresponds to the given file. FileID FirstFID; // First, check the main file ID, since it is common to look for a // location in the main file. llvm::Optional<ino_t> SourceFileInode; - llvm::Optional<llvm::StringRef> SourceFileName; + llvm::Optional<StringRef> SourceFileName; if (!MainFileID.isInvalid()) { bool Invalid = false; const SLocEntry &MainSLoc = getSLocEntry(MainFileID, &Invalid); if (Invalid) - return SourceLocation(); + return FileID(); if (MainSLoc.isFile()) { const ContentCache *MainContentCache @@ -1308,12 +1401,12 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile, if (FirstFID.isInvalid()) { // 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) { + // through all of the local source locations. + for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) { bool Invalid = false; - const SLocEntry &SLoc = getSLocEntry(I, &Invalid); + const SLocEntry &SLoc = getLocalSLocEntry(I, &Invalid); if (Invalid) - return SourceLocation(); + return FileID(); if (SLoc.isFile() && SLoc.getFile().getContentCache() && @@ -1322,6 +1415,18 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile, break; } } + // If that still didn't help, try the modules. + if (FirstFID.isInvalid()) { + for (unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) { + const SLocEntry &SLoc = getLoadedSLocEntry(I); + if (SLoc.isFile() && + SLoc.getFile().getContentCache() && + SLoc.getFile().getContentCache()->OrigEntry == SourceFile) { + FirstFID = FileID::get(-int(I) - 2); + break; + } + } + } } // If we haven't found what we want yet, try again, but this time stat() @@ -1333,10 +1438,12 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile, (SourceFileInode || (SourceFileInode = getActualFileInode(SourceFile)))) { bool Invalid = false; - for (unsigned I = 0, N = sloc_entry_size(); I != N; ++I) { - const SLocEntry &SLoc = getSLocEntry(I, &Invalid); + for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) { + FileID IFileID; + IFileID.ID = I; + const SLocEntry &SLoc = getSLocEntry(IFileID, &Invalid); if (Invalid) - return SourceLocation(); + return FileID(); if (SLoc.isFile()) { const ContentCache *FileContentCache @@ -1355,20 +1462,38 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile, } } } - - if (FirstFID.isInvalid()) + + return FirstFID; +} + +/// \brief Get the source location in \arg FID for the given line:col. +/// Returns null location if \arg FID is not a file SLocEntry. +SourceLocation SourceManager::translateLineCol(FileID FID, + unsigned Line, + unsigned Col) const { + if (FID.isInvalid()) + return SourceLocation(); + + bool Invalid = false; + const SLocEntry &Entry = getSLocEntry(FID, &Invalid); + if (Invalid) + return SourceLocation(); + + if (!Entry.isFile()) return SourceLocation(); + SourceLocation FileLoc = SourceLocation::getFileLoc(Entry.getOffset()); + if (Line == 1 && Col == 1) - return getLocForStartOfFile(FirstFID); + return FileLoc; ContentCache *Content - = const_cast<ContentCache *>(getOrCreateContentCache(SourceFile)); + = const_cast<ContentCache *>(Entry.getFile().getContentCache()); if (!Content) return SourceLocation(); // If this is the first use of line information for this buffer, compute the - /// SourceLineCache for it on demand. + // SourceLineCache for it on demand. if (Content->SourceLineCache == 0) { bool MyInvalid = false; ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid); @@ -1380,33 +1505,150 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile, unsigned Size = Content->getBuffer(Diag, *this)->getBufferSize(); if (Size > 0) --Size; - return getLocForStartOfFile(FirstFID).getFileLocWithOffset(Size); + return FileLoc.getLocWithOffset(Size); } unsigned FilePos = Content->SourceLineCache[Line - 1]; const char *Buf = Content->getBuffer(Diag, *this)->getBufferStart() + FilePos; unsigned BufLength = Content->getBuffer(Diag, *this)->getBufferEnd() - Buf; + if (BufLength == 0) + return FileLoc.getLocWithOffset(FilePos); + unsigned i = 0; // Check that the given column is valid. while (i < BufLength-1 && i < Col-1 && Buf[i] != '\n' && Buf[i] != '\r') ++i; if (i < Col-1) - return getLocForStartOfFile(FirstFID).getFileLocWithOffset(FilePos + i); + return FileLoc.getLocWithOffset(FilePos + i); - return getLocForStartOfFile(FirstFID).getFileLocWithOffset(FilePos + Col - 1); + return FileLoc.getLocWithOffset(FilePos + Col - 1); } -/// Given a decomposed source location, move it up the include/instantiation -/// stack to the parent source location. If this is possible, return the -/// decomposed version of the parent in Loc and return false. If Loc is the -/// top-level entry, return true and don't modify it. +/// \brief Compute a map of macro argument chunks to their expanded source +/// location. Chunks that are not part of a macro argument will map to an +/// invalid source location. e.g. if a file contains one macro argument at +/// offset 100 with length 10, this is how the map will be formed: +/// 0 -> SourceLocation() +/// 100 -> Expanded macro arg location +/// 110 -> SourceLocation() +void SourceManager::computeMacroArgsCache(MacroArgsMap *&CachePtr, + FileID FID) const { + assert(!FID.isInvalid()); + assert(!CachePtr); + + CachePtr = new MacroArgsMap(); + MacroArgsMap &MacroArgsCache = *CachePtr; + // Initially no macro argument chunk is present. + MacroArgsCache.insert(std::make_pair(0, SourceLocation())); + + int ID = FID.ID; + while (1) { + ++ID; + // Stop if there are no more FileIDs to check. + if (ID > 0) { + if (unsigned(ID) >= local_sloc_entry_size()) + return; + } else if (ID == -1) { + return; + } + + const SrcMgr::SLocEntry &Entry = getSLocEntryByID(ID); + if (Entry.isFile()) { + SourceLocation IncludeLoc = Entry.getFile().getIncludeLoc(); + if (IncludeLoc.isInvalid()) + continue; + if (!isInFileID(IncludeLoc, FID)) + return; // No more files/macros that may be "contained" in this file. + + // Skip the files/macros of the #include'd file, we only care about macros + // that lexed macro arguments from our file. + if (Entry.getFile().NumCreatedFIDs) + ID += Entry.getFile().NumCreatedFIDs - 1/*because of next ++ID*/; + continue; + } + + if (!Entry.getExpansion().isMacroArgExpansion()) + continue; + + SourceLocation SpellLoc = + getSpellingLoc(Entry.getExpansion().getSpellingLoc()); + unsigned BeginOffs; + if (!isInFileID(SpellLoc, FID, &BeginOffs)) + return; // No more files/macros that may be "contained" in this file. + unsigned EndOffs = BeginOffs + getFileIDSize(FileID::get(ID)); + + // Add a new chunk for this macro argument. A previous macro argument chunk + // may have been lexed again, so e.g. if the map is + // 0 -> SourceLocation() + // 100 -> Expanded loc #1 + // 110 -> SourceLocation() + // and we found a new macro FileID that lexed from offet 105 with length 3, + // the new map will be: + // 0 -> SourceLocation() + // 100 -> Expanded loc #1 + // 105 -> Expanded loc #2 + // 108 -> Expanded loc #1 + // 110 -> SourceLocation() + // + // Since re-lexed macro chunks will always be the same size or less of + // previous chunks, we only need to find where the ending of the new macro + // chunk is mapped to and update the map with new begin/end mappings. + + MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs); + --I; + SourceLocation EndOffsMappedLoc = I->second; + MacroArgsCache[BeginOffs] = SourceLocation::getMacroLoc(Entry.getOffset()); + MacroArgsCache[EndOffs] = EndOffsMappedLoc; + } +} + +/// \brief If \arg Loc points inside a function macro argument, the returned +/// location will be the macro location in which the argument was expanded. +/// If a macro argument is used multiple times, the expanded location will +/// be at the first expansion of the argument. +/// e.g. +/// MY_MACRO(foo); +/// ^ +/// Passing a file location pointing at 'foo', will yield a macro location +/// where 'foo' was expanded into. +SourceLocation +SourceManager::getMacroArgExpandedLocation(SourceLocation Loc) const { + if (Loc.isInvalid() || !Loc.isFileID()) + return Loc; + + FileID FID; + unsigned Offset; + llvm::tie(FID, Offset) = getDecomposedLoc(Loc); + if (FID.isInvalid()) + return Loc; + + MacroArgsMap *&MacroArgsCache = MacroArgsCacheMap[FID]; + if (!MacroArgsCache) + computeMacroArgsCache(MacroArgsCache, FID); + + assert(!MacroArgsCache->empty()); + MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset); + --I; + + unsigned MacroArgBeginOffs = I->first; + SourceLocation MacroArgExpandedLoc = I->second; + if (MacroArgExpandedLoc.isValid()) + return MacroArgExpandedLoc.getLocWithOffset(Offset - MacroArgBeginOffs); + + return Loc; +} + +/// Given a decomposed source location, move it up the include/expansion stack +/// to the parent source location. If this is possible, return the decomposed +/// version of the parent in Loc and return false. If Loc is the top-level +/// entry, return true and don't modify it. static bool MoveUpIncludeHierarchy(std::pair<FileID, unsigned> &Loc, const SourceManager &SM) { SourceLocation UpperLoc; const SrcMgr::SLocEntry &Entry = SM.getSLocEntry(Loc.first); - if (Entry.isInstantiation()) - UpperLoc = Entry.getInstantiation().getInstantiationLocStart(); + if (Entry.isExpansion()) + UpperLoc = Entry.getExpansion().getExpansionLocEnd(); else UpperLoc = Entry.getFile().getIncludeLoc(); @@ -1427,11 +1669,6 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS, if (LHS == RHS) return false; - // If both locations are macro instantiations, the order of their offsets - // reflect the order that the tokens, pointed to by these locations, were - // instantiated (during parsing each token that is instantiated by a macro, - // expands the SLocEntries). - std::pair<FileID, unsigned> LOffs = getDecomposedLoc(LHS); std::pair<FileID, unsigned> ROffs = getDecomposedLoc(RHS); @@ -1445,41 +1682,28 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS, return IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second); // Okay, we missed in the cache, start updating the cache for this query. - IsBeforeInTUCache.setQueryFIDs(LOffs.first, ROffs.first); - - // "Traverse" the include/instantiation stacks of both locations and try to - // find a common "ancestor". FileIDs build a tree-like structure that - // reflects the #include hierarchy, and this algorithm needs to find the - // nearest common ancestor between the two locations. For example, if you - // have a.c that includes b.h and c.h, and are comparing a location in b.h to - // a location in c.h, we need to find that their nearest common ancestor is - // a.c, and compare the locations of the two #includes to find their relative - // ordering. - // - // SourceManager assigns FileIDs in order of parsing. This means that an - // includee always has a larger FileID than an includer. While you might - // think that we could just compare the FileID's here, that doesn't work to - // compare a point at the end of a.c with a point within c.h. Though c.h has - // a larger FileID, we have to compare the include point of c.h to the - // location in a.c. - // - // Despite not being able to directly compare FileID's, we can tell that a - // larger FileID is necessarily more deeply nested than a lower one and use - // this information to walk up the tree to the nearest common ancestor. + IsBeforeInTUCache.setQueryFIDs(LOffs.first, ROffs.first, + /*isLFIDBeforeRFID=*/LOffs.first.ID < ROffs.first.ID); + + // We need to find the common ancestor. The only way of doing this is to + // build the complete include chain for one and then walking up the chain + // of the other looking for a match. + // We use a map from FileID to Offset to store the chain. Easier than writing + // a custom set hash info that only depends on the first part of a pair. + typedef llvm::DenseMap<FileID, unsigned> LocSet; + LocSet LChain; do { - // If LOffs is larger than ROffs, then LOffs must be more deeply nested than - // ROffs, walk up the #include chain. - if (LOffs.first.ID > ROffs.first.ID) { - if (MoveUpIncludeHierarchy(LOffs, *this)) - break; // We reached the top. - - } else { - // Otherwise, ROffs is larger than LOffs, so ROffs must be more deeply - // nested than LOffs, walk up the #include chain. - if (MoveUpIncludeHierarchy(ROffs, *this)) - break; // We reached the top. - } - } while (LOffs.first != ROffs.first); + LChain.insert(LOffs); + // We catch the case where LOffs is in a file included by ROffs and + // quit early. The other way round unfortunately remains suboptimal. + } while (LOffs.first != ROffs.first && !MoveUpIncludeHierarchy(LOffs, *this)); + LocSet::iterator I; + while((I = LChain.find(ROffs.first)) == LChain.end()) { + if (MoveUpIncludeHierarchy(ROffs, *this)) + break; // Met at topmost file. + } + if (I != LChain.end()) + LOffs = *I; // If we exited because we found a nearest common ancestor, compare the // locations within the common file and cache them. @@ -1488,26 +1712,21 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS, return IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second); } - // There is no common ancestor, most probably because one location is in the - // predefines buffer or an AST file. - // FIXME: We should rearrange the external interface so this simply never - // happens; it can't conceptually happen. Also see PR5662. - IsBeforeInTUCache.setQueryFIDs(FileID(), FileID()); // Don't try caching. - - // Zip both entries up to the top level record. - while (!MoveUpIncludeHierarchy(LOffs, *this)) /*empty*/; - while (!MoveUpIncludeHierarchy(ROffs, *this)) /*empty*/; - - // 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. - bool LIsMB = getFileEntryForID(LOffs.first) == 0; - bool RIsMB = getFileEntryForID(ROffs.first) == 0; - if (LIsMB != RIsMB) - return LIsMB; - - // Otherwise, just assume FileIDs were created in order. + // This can happen if a location is in a built-ins buffer. + // But see PR5662. + // Clear the lookup cache, it depends on a common location. + IsBeforeInTUCache.clear(); + bool LIsBuiltins = strcmp("<built-in>", + getBuffer(LOffs.first)->getBufferIdentifier()) == 0; + bool RIsBuiltins = strcmp("<built-in>", + getBuffer(ROffs.first)->getBufferIdentifier()) == 0; + // built-in is before non-built-in + if (LIsBuiltins != RIsBuiltins) + return LIsBuiltins; + assert(LIsBuiltins && RIsBuiltins && + "Non-built-in locations must be rooted in the main file"); + // Both are in built-in buffers, but from different files. We just claim that + // lower IDs come first. return LOffs.first < ROffs.first; } @@ -1517,20 +1736,26 @@ void SourceManager::PrintStats() const { 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 (" - << SLocEntryTable.capacity()*sizeof(SrcMgr::SLocEntry) + llvm::errs() << LocalSLocEntryTable.size() << " local SLocEntry's allocated (" + << llvm::capacity_in_bytes(LocalSLocEntryTable) << " bytes of capacity), " - << NextOffset << "B of Sloc address space used.\n"; - + << NextLocalOffset << "B of Sloc address space used.\n"; + llvm::errs() << LoadedSLocEntryTable.size() + << " loaded SLocEntries allocated, " + << MaxLoadedOffset - CurrentLoadedOffset + << "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(); } + unsigned NumMacroArgsComputed = MacroArgsCacheMap.size(); llvm::errs() << NumFileBytesMapped << " bytes of files mapped, " - << NumLineNumsComputed << " files with line #'s computed.\n"; + << NumLineNumsComputed << " files with line #'s computed, " + << NumMacroArgsComputed << " files with macro args computed.\n"; llvm::errs() << "FileID scans: " << NumLinearScans << " linear, " << NumBinaryProbes << " binary.\n"; } @@ -1557,3 +1782,11 @@ SourceManager::MemoryBufferSizes SourceManager::getMemoryBufferSizes() const { return MemoryBufferSizes(malloc_bytes, mmap_bytes); } +size_t SourceManager::getDataStructureSizes() const { + return llvm::capacity_in_bytes(MemBufferInfos) + + llvm::capacity_in_bytes(LocalSLocEntryTable) + + llvm::capacity_in_bytes(LoadedSLocEntryTable) + + llvm::capacity_in_bytes(SLocEntryLoaded) + + llvm::capacity_in_bytes(FileInfos) + + llvm::capacity_in_bytes(OverriddenFiles); +} diff --git a/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp index 30a9bdb..593db2b 100644 --- a/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp @@ -16,6 +16,7 @@ #include "clang/Basic/LangOptions.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/ErrorHandling.h" #include <cctype> #include <cstdlib> using namespace clang; @@ -33,6 +34,8 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) { IntWidth = IntAlign = 32; LongWidth = LongAlign = 32; LongLongWidth = LongLongAlign = 64; + HalfWidth = 16; + HalfAlign = 16; FloatWidth = 32; FloatAlign = 32; DoubleWidth = 64; @@ -41,6 +44,7 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) { LongDoubleAlign = 64; LargeArrayMinWidth = 0; LargeArrayAlign = 0; + MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0; SizeType = UnsignedLong; PtrDiffType = SignedLong; IntMaxType = SignedLongLong; @@ -53,6 +57,9 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) { Int64Type = SignedLongLong; SigAtomicType = SignedInt; UseBitFieldTypeAlignment = true; + UseZeroLengthBitfieldAlignment = false; + ZeroLengthBitfieldBoundary = 0; + HalfFormat = &llvm::APFloat::IEEEhalf; FloatFormat = &llvm::APFloat::IEEEsingle; DoubleFormat = &llvm::APFloat::IEEEdouble; LongDoubleFormat = &llvm::APFloat::IEEEdouble; @@ -60,6 +67,8 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) { "i64:64:64-f32:32:32-f64:64:64-n32"; UserLabelPrefix = "_"; MCountName = "mcount"; + RegParmMax = 0; + SSERegParmMax = 0; HasAlignMac68kSupport = false; // Default to no types using fpret. @@ -83,7 +92,7 @@ TargetInfo::~TargetInfo() {} /// For example, SignedShort -> "short". const char *TargetInfo::getTypeName(IntType T) { switch (T) { - default: assert(0 && "not an integer!"); + default: llvm_unreachable("not an integer!"); case SignedShort: return "short"; case UnsignedShort: return "unsigned short"; case SignedInt: return "int"; @@ -99,7 +108,7 @@ const char *TargetInfo::getTypeName(IntType T) { /// integer type enum. For example, SignedLong -> "L". const char *TargetInfo::getTypeConstantSuffix(IntType T) { switch (T) { - default: assert(0 && "not an integer!"); + default: llvm_unreachable("not an integer!"); case SignedShort: case SignedInt: return ""; case SignedLong: return "L"; @@ -115,7 +124,7 @@ const char *TargetInfo::getTypeConstantSuffix(IntType T) { /// enum. For example, SignedInt -> getIntWidth(). unsigned TargetInfo::getTypeWidth(IntType T) const { switch (T) { - default: assert(0 && "not an integer!"); + default: llvm_unreachable("not an integer!"); case SignedShort: case UnsignedShort: return getShortWidth(); case SignedInt: @@ -131,7 +140,7 @@ unsigned TargetInfo::getTypeWidth(IntType T) const { /// enum. For example, SignedInt -> getIntAlign(). unsigned TargetInfo::getTypeAlign(IntType T) const { switch (T) { - default: assert(0 && "not an integer!"); + default: llvm_unreachable("not an integer!"); case SignedShort: case UnsignedShort: return getShortAlign(); case SignedInt: @@ -147,7 +156,7 @@ unsigned TargetInfo::getTypeAlign(IntType T) const { /// the type is signed; false otherwise. bool TargetInfo::isTypeSigned(IntType T) { switch (T) { - default: assert(0 && "not an integer!"); + default: llvm_unreachable("not an integer!"); case SignedShort: case SignedInt: case SignedLong: @@ -174,7 +183,7 @@ void TargetInfo::setForcedLangOptions(LangOptions &Opts) { //===----------------------------------------------------------------------===// -static llvm::StringRef removeGCCRegisterPrefix(llvm::StringRef Name) { +static StringRef removeGCCRegisterPrefix(StringRef Name) { if (Name[0] == '%' || Name[0] == '#') Name = Name.substr(1); @@ -184,7 +193,7 @@ static llvm::StringRef removeGCCRegisterPrefix(llvm::StringRef Name) { /// isValidClobber - Returns whether the passed in string is /// a valid clobber in an inline asm statement. This is used by /// Sema. -bool TargetInfo::isValidClobber(llvm::StringRef Name) const { +bool TargetInfo::isValidClobber(StringRef Name) const { return (isValidGCCRegisterName(Name) || Name == "memory" || Name == "cc"); } @@ -192,7 +201,7 @@ bool TargetInfo::isValidClobber(llvm::StringRef Name) const { /// isValidGCCRegisterName - Returns whether the passed in string /// is a valid register name according to GCC. This is used by Sema for /// inline asm statements. -bool TargetInfo::isValidGCCRegisterName(llvm::StringRef Name) const { +bool TargetInfo::isValidGCCRegisterName(StringRef Name) const { if (Name.empty()) return false; @@ -248,8 +257,8 @@ bool TargetInfo::isValidGCCRegisterName(llvm::StringRef Name) const { return false; } -llvm::StringRef -TargetInfo::getNormalizedGCCRegisterName(llvm::StringRef Name) const { +StringRef +TargetInfo::getNormalizedGCCRegisterName(StringRef Name) const { assert(isValidGCCRegisterName(Name) && "Invalid register passed in"); // Get rid of any register prefix. diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp index 4c1eeed..6d0d7bb 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp @@ -26,6 +26,7 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/MC/MCSectionMachO.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Type.h" #include <algorithm> using namespace clang; @@ -37,7 +38,7 @@ using namespace clang; /// DefineStd - Define a macro name and standard variants. For example if /// MacroName is "unix", then this will define "__unix", "__unix__", and "unix" /// when in GNU mode. -static void DefineStd(MacroBuilder &Builder, llvm::StringRef MacroName, +static void DefineStd(MacroBuilder &Builder, StringRef MacroName, const LangOptions &Opts) { assert(MacroName[0] != '_' && "Identifier should be in the user's namespace"); @@ -77,7 +78,7 @@ public: static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts, const llvm::Triple &Triple, - llvm::StringRef &PlatformName, + StringRef &PlatformName, VersionTuple &PlatformMinVersion) { Builder.defineMacro("__APPLE_CC__", "5621"); Builder.defineMacro("__APPLE__"); @@ -89,7 +90,7 @@ static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts, Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))"); // Darwin defines __strong even in C mode (just to nothing). - if (Opts.getGCMode() != LangOptions::NonGC) + if (Opts.getGC() != LangOptions::NonGC) Builder.defineMacro("__strong", "__attribute__((objc_gc(strong)))"); else Builder.defineMacro("__strong", ""); @@ -146,6 +147,14 @@ static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts, } } + // If -ccc-host-triple arch-pc-win32-macho option specified, we're + // generating code for Win32 ABI. No need to emit + // __ENVIRONMENT_XX_OS_VERSION_MIN_REQUIRED__. + if (PlatformName == "win32") { + PlatformMinVersion = VersionTuple(Maj, Min, Rev); + return; + } + // Set the appropriate OS version define. if (PlatformName == "ios") { assert(Maj < 10 && Min < 100 && Rev < 100 && "Invalid version!"); @@ -194,9 +203,9 @@ public: this->MCountName = "\01mcount"; } - virtual std::string isValidSectionSpecifier(llvm::StringRef SR) const { + virtual std::string isValidSectionSpecifier(StringRef SR) const { // Let MCSectionMachO validate this. - llvm::StringRef Segment, Section; + StringRef Segment, Section; unsigned TAA, StubSize; bool HasTAA; return llvm::MCSectionMachO::ParseSectionSpecifier(SR, Segment, Section, @@ -242,9 +251,8 @@ protected: if (Release == 0U) Release = 8U; - Builder.defineMacro("__FreeBSD__", llvm::Twine(Release)); - Builder.defineMacro("__FreeBSD_cc_version", - llvm::Twine(Release * 100000U + 1U)); + Builder.defineMacro("__FreeBSD__", Twine(Release)); + Builder.defineMacro("__FreeBSD_cc_version", Twine(Release * 100000U + 1U)); Builder.defineMacro("__KPRINTF_ATTRIBUTE__"); DefineStd(Builder, "unix", Opts); Builder.defineMacro("__ELF__"); @@ -497,9 +505,9 @@ protected: Builder.defineMacro("_MT"); if (Opts.MSCVersion != 0) - Builder.defineMacro("_MSC_VER", llvm::Twine(Opts.MSCVersion)); + Builder.defineMacro("_MSC_VER", Twine(Opts.MSCVersion)); - if (Opts.Microsoft) { + if (Opts.MicrosoftExt) { Builder.defineMacro("_MSC_EXTENSIONS"); if (Opts.CPlusPlus0x) { @@ -871,13 +879,41 @@ public: } // end anonymous namespace. namespace { + static const unsigned PTXAddrSpaceMap[] = { + 0, // opencl_global + 4, // opencl_local + 1 // opencl_constant + }; class PTXTargetInfo : public TargetInfo { static const char * const GCCRegNames[]; static const Builtin::Info BuiltinInfo[]; + std::vector<llvm::StringRef> AvailableFeatures; public: PTXTargetInfo(const std::string& triple) : TargetInfo(triple) { TLSSupported = false; LongWidth = LongAlign = 64; + AddrSpaceMap = &PTXAddrSpaceMap; + // Define available target features + // These must be defined in sorted order! + AvailableFeatures.push_back("compute10"); + AvailableFeatures.push_back("compute11"); + AvailableFeatures.push_back("compute12"); + AvailableFeatures.push_back("compute13"); + AvailableFeatures.push_back("compute20"); + AvailableFeatures.push_back("double"); + AvailableFeatures.push_back("no-fma"); + AvailableFeatures.push_back("ptx20"); + AvailableFeatures.push_back("ptx21"); + AvailableFeatures.push_back("ptx22"); + AvailableFeatures.push_back("ptx23"); + AvailableFeatures.push_back("sm10"); + AvailableFeatures.push_back("sm11"); + AvailableFeatures.push_back("sm12"); + AvailableFeatures.push_back("sm13"); + AvailableFeatures.push_back("sm20"); + AvailableFeatures.push_back("sm21"); + AvailableFeatures.push_back("sm22"); + AvailableFeatures.push_back("sm23"); } virtual void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { @@ -910,6 +946,10 @@ namespace { // FIXME: implement return "typedef char* __builtin_va_list;"; } + + virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features, + const std::string &Name, + bool Enabled) const; }; const Builtin::Info PTXTargetInfo::BuiltinInfo[] = { @@ -929,6 +969,17 @@ namespace { NumNames = llvm::array_lengthof(GCCRegNames); } + bool PTXTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, + const std::string &Name, + bool Enabled) const { + if(std::binary_search(AvailableFeatures.begin(), AvailableFeatures.end(), + Name)) { + Features[Name] = Enabled; + return true; + } else { + return false; + } + } class PTX32TargetInfo : public PTXTargetInfo { public: @@ -1121,10 +1172,134 @@ class X86TargetInfo : public TargetInfo { bool HasAES; bool HasAVX; + /// \brief Enumeration of all of the X86 CPUs supported by Clang. + /// + /// Each enumeration represents a particular CPU supported by Clang. These + /// loosely correspond to the options passed to '-march' or '-mtune' flags. + enum CPUKind { + CK_Generic, + + /// \name i386 + /// i386-generation processors. + //@{ + CK_i386, + //@} + + /// \name i486 + /// i486-generation processors. + //@{ + CK_i486, + CK_WinChipC6, + CK_WinChip2, + CK_C3, + //@} + + /// \name i586 + /// i586-generation processors, P5 microarchitecture based. + //@{ + CK_i586, + CK_Pentium, + CK_PentiumMMX, + //@} + + /// \name i686 + /// i686-generation processors, P6 / Pentium M microarchitecture based. + //@{ + CK_i686, + CK_PentiumPro, + CK_Pentium2, + CK_Pentium3, + CK_Pentium3M, + CK_PentiumM, + CK_C3_2, + + /// This enumerator is a bit odd, as GCC no longer accepts -march=yonah. + /// Clang however has some logic to suport this. + // FIXME: Warn, deprecate, and potentially remove this. + CK_Yonah, + //@} + + /// \name Netburst + /// Netburst microarchitecture based processors. + //@{ + CK_Pentium4, + CK_Pentium4M, + CK_Prescott, + CK_Nocona, + //@} + + /// \name Core + /// Core microarchitecture based processors. + //@{ + CK_Core2, + + /// This enumerator, like \see CK_Yonah, is a bit odd. It is another + /// codename which GCC no longer accepts as an option to -march, but Clang + /// has some logic for recognizing it. + // FIXME: Warn, deprecate, and potentially remove this. + CK_Penryn, + //@} + + /// \name Atom + /// Atom processors + //@{ + CK_Atom, + //@} + + /// \name Nehalem + /// Nehalem microarchitecture based processors. + //@{ + CK_Corei7, + CK_Corei7AVX, + CK_CoreAVXi, + //@} + + /// \name K6 + /// K6 architecture processors. + //@{ + CK_K6, + CK_K6_2, + CK_K6_3, + //@} + + /// \name K7 + /// K7 architecture processors. + //@{ + CK_Athlon, + CK_AthlonThunderbird, + CK_Athlon4, + CK_AthlonXP, + CK_AthlonMP, + //@} + + /// \name K8 + /// K8 architecture processors. + //@{ + CK_Athlon64, + CK_Athlon64SSE3, + CK_AthlonFX, + CK_K8, + CK_K8SSE3, + CK_Opteron, + CK_OpteronSSE3, + + /// This specification is deprecated and will be removed in the future. + /// Users should prefer \see CK_K8. + // FIXME: Warn on this when the CPU is set to it. + CK_x86_64, + //@} + + /// \name Geode + /// Geode processors. + //@{ + CK_Geode + //@} + } CPU; + public: X86TargetInfo(const std::string& triple) : TargetInfo(triple), SSELevel(NoSSE), MMX3DNowLevel(NoMMX3DNow), - HasAES(false), HasAVX(false) { + HasAES(false), HasAVX(false), CPU(CK_Generic) { LongDoubleFormat = &llvm::APFloat::x87DoubleExtended; } virtual void getTargetBuiltins(const Builtin::Info *&Records, @@ -1158,16 +1333,122 @@ public: virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features, const std::string &Name, bool Enabled) const; - virtual void getDefaultFeatures(const std::string &CPU, - llvm::StringMap<bool> &Features) const; + virtual void getDefaultFeatures(llvm::StringMap<bool> &Features) const; virtual void HandleTargetFeatures(std::vector<std::string> &Features); virtual const char* getABI() const { return MMX3DNowLevel == NoMMX3DNow ? "no-mmx" : ""; } + virtual bool setCPU(const std::string &Name) { + CPU = llvm::StringSwitch<CPUKind>(Name) + .Case("i386", CK_i386) + .Case("i486", CK_i486) + .Case("winchip-c6", CK_WinChipC6) + .Case("winchip2", CK_WinChip2) + .Case("c3", CK_C3) + .Case("i586", CK_i586) + .Case("pentium", CK_Pentium) + .Case("pentium-mmx", CK_PentiumMMX) + .Case("i686", CK_i686) + .Case("pentiumpro", CK_PentiumPro) + .Case("pentium2", CK_Pentium2) + .Case("pentium3", CK_Pentium3) + .Case("pentium3m", CK_Pentium3M) + .Case("pentium-m", CK_PentiumM) + .Case("c3-2", CK_C3_2) + .Case("yonah", CK_Yonah) + .Case("pentium4", CK_Pentium4) + .Case("pentium4m", CK_Pentium4M) + .Case("prescott", CK_Prescott) + .Case("nocona", CK_Nocona) + .Case("core2", CK_Core2) + .Case("penryn", CK_Penryn) + .Case("atom", CK_Atom) + .Case("corei7", CK_Corei7) + .Case("corei7-avx", CK_Corei7AVX) + .Case("core-avx-i", CK_CoreAVXi) + .Case("k6", CK_K6) + .Case("k6-2", CK_K6_2) + .Case("k6-3", CK_K6_3) + .Case("athlon", CK_Athlon) + .Case("athlon-tbird", CK_AthlonThunderbird) + .Case("athlon-4", CK_Athlon4) + .Case("athlon-xp", CK_AthlonXP) + .Case("athlon-mp", CK_AthlonMP) + .Case("athlon64", CK_Athlon64) + .Case("athlon64-sse3", CK_Athlon64SSE3) + .Case("athlon-fx", CK_AthlonFX) + .Case("k8", CK_K8) + .Case("k8-sse3", CK_K8SSE3) + .Case("opteron", CK_Opteron) + .Case("opteron-sse3", CK_OpteronSSE3) + .Case("x86-64", CK_x86_64) + .Case("geode", CK_Geode) + .Default(CK_Generic); + + // Perform any per-CPU checks necessary to determine if this CPU is + // acceptable. + // FIXME: This results in terrible diagnostics. Clang just says the CPU is + // invalid without explaining *why*. + switch (CPU) { + case CK_Generic: + // No processor selected! + return false; + + case CK_i386: + case CK_i486: + case CK_WinChipC6: + case CK_WinChip2: + case CK_C3: + case CK_i586: + case CK_Pentium: + case CK_PentiumMMX: + case CK_i686: + case CK_PentiumPro: + case CK_Pentium2: + case CK_Pentium3: + case CK_Pentium3M: + case CK_PentiumM: + case CK_Yonah: + case CK_C3_2: + case CK_Pentium4: + case CK_Pentium4M: + case CK_Prescott: + case CK_K6: + case CK_K6_2: + case CK_K6_3: + case CK_Athlon: + case CK_AthlonThunderbird: + case CK_Athlon4: + case CK_AthlonXP: + case CK_AthlonMP: + case CK_Geode: + // Only accept certain architectures when compiling in 32-bit mode. + if (PointerWidth != 32) + return false; + + // Fallthrough + case CK_Nocona: + case CK_Core2: + case CK_Penryn: + case CK_Atom: + case CK_Corei7: + case CK_Corei7AVX: + case CK_CoreAVXi: + case CK_Athlon64: + case CK_Athlon64SSE3: + case CK_AthlonFX: + case CK_K8: + case CK_K8SSE3: + case CK_Opteron: + case CK_OpteronSSE3: + case CK_x86_64: + return true; + } + llvm_unreachable("Unhandled CPU kind"); + } }; -void X86TargetInfo::getDefaultFeatures(const std::string &CPU, - llvm::StringMap<bool> &Features) const { +void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const { // FIXME: This should not be here. Features["3dnow"] = false; Features["3dnowa"] = false; @@ -1190,57 +1471,100 @@ void X86TargetInfo::getDefaultFeatures(const std::string &CPU, if (PointerWidth == 64) Features["sse2"] = Features["sse"] = Features["mmx"] = true; - if (CPU == "generic" || CPU == "i386" || CPU == "i486" || CPU == "i586" || - CPU == "pentium" || CPU == "i686" || CPU == "pentiumpro") - ; - else if (CPU == "pentium-mmx" || CPU == "pentium2") + switch (CPU) { + case CK_Generic: + case CK_i386: + case CK_i486: + case CK_i586: + case CK_Pentium: + case CK_i686: + case CK_PentiumPro: + break; + case CK_PentiumMMX: + case CK_Pentium2: setFeatureEnabled(Features, "mmx", true); - else if (CPU == "pentium3") { + break; + case CK_Pentium3: + case CK_Pentium3M: setFeatureEnabled(Features, "mmx", true); setFeatureEnabled(Features, "sse", true); - } else if (CPU == "pentium-m" || CPU == "pentium4" || CPU == "x86-64") { + break; + case CK_PentiumM: + case CK_Pentium4: + case CK_Pentium4M: + case CK_x86_64: setFeatureEnabled(Features, "mmx", true); setFeatureEnabled(Features, "sse2", true); - } else if (CPU == "yonah" || CPU == "prescott" || CPU == "nocona") { + break; + case CK_Yonah: + case CK_Prescott: + case CK_Nocona: setFeatureEnabled(Features, "mmx", true); setFeatureEnabled(Features, "sse3", true); - } else if (CPU == "core2") { + break; + case CK_Core2: setFeatureEnabled(Features, "mmx", true); setFeatureEnabled(Features, "ssse3", true); - } else if (CPU == "penryn") { + break; + case CK_Penryn: setFeatureEnabled(Features, "mmx", true); setFeatureEnabled(Features, "sse4", true); Features["sse42"] = false; - } else if (CPU == "atom") { + break; + case CK_Atom: setFeatureEnabled(Features, "mmx", true); - setFeatureEnabled(Features, "sse3", true); - } else if (CPU == "corei7") { + setFeatureEnabled(Features, "ssse3", true); + break; + case CK_Corei7: setFeatureEnabled(Features, "mmx", true); setFeatureEnabled(Features, "sse4", true); setFeatureEnabled(Features, "aes", true); - } else if (CPU == "corei7-avx") { + break; + case CK_Corei7AVX: + case CK_CoreAVXi: setFeatureEnabled(Features, "mmx", true); setFeatureEnabled(Features, "sse4", true); setFeatureEnabled(Features, "aes", true); //setFeatureEnabled(Features, "avx", true); - } else if (CPU == "k6" || CPU == "winchip-c6") + break; + case CK_K6: + case CK_WinChipC6: setFeatureEnabled(Features, "mmx", true); - else if (CPU == "k6-2" || CPU == "k6-3" || CPU == "athlon" || - CPU == "athlon-tbird" || CPU == "winchip2" || CPU == "c3") { + break; + case CK_K6_2: + case CK_K6_3: + case CK_WinChip2: + case CK_C3: setFeatureEnabled(Features, "3dnow", true); - } else if (CPU == "athlon-4" || CPU == "athlon-xp" || CPU == "athlon-mp") { + break; + case CK_Athlon: + case CK_AthlonThunderbird: + case CK_Geode: + setFeatureEnabled(Features, "3dnowa", true); + break; + case CK_Athlon4: + case CK_AthlonXP: + case CK_AthlonMP: setFeatureEnabled(Features, "sse", true); setFeatureEnabled(Features, "3dnowa", true); - } else if (CPU == "k8" || CPU == "opteron" || CPU == "athlon64" || - CPU == "athlon-fx") { + break; + case CK_K8: + case CK_Opteron: + case CK_Athlon64: + case CK_AthlonFX: setFeatureEnabled(Features, "sse2", true); setFeatureEnabled(Features, "3dnowa", true); - } else if (CPU == "k8-sse3") { + break; + case CK_K8SSE3: + case CK_OpteronSSE3: + case CK_Athlon64SSE3: setFeatureEnabled(Features, "sse3", true); setFeatureEnabled(Features, "3dnowa", true); - } else if (CPU == "c3-2") { + break; + case CK_C3_2: setFeatureEnabled(Features, "mmx", true); setFeatureEnabled(Features, "sse", true); + break; } } @@ -1278,7 +1602,8 @@ bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, else if (Name == "aes") Features["aes"] = true; else if (Name == "avx") - Features["avx"] = true; + Features["avx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = + Features["ssse3"] = Features["sse41"] = Features["sse42"] = true; } else { if (Name == "mmx") Features["mmx"] = Features["3dnow"] = Features["3dnowa"] = false; @@ -1360,8 +1685,8 @@ void X86TargetInfo::HandleTargetFeatures(std::vector<std::string> &Features) { Features.erase(it); } -/// X86TargetInfo::getTargetDefines - Return a set of the X86-specific #defines -/// that are not tied to a specific subtarget. +/// X86TargetInfo::getTargetDefines - Return the set of the X86-specific macro +/// definitions for this particular subtarget. void X86TargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { // Target identification. @@ -1376,19 +1701,140 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, DefineStd(Builder, "i386", Opts); } - if (HasAES) - Builder.defineMacro("__AES__"); - - if (HasAVX) - Builder.defineMacro("__AVX__"); + // Subtarget options. + // FIXME: We are hard-coding the tune parameters based on the CPU, but they + // truly should be based on -mtune options. + switch (CPU) { + case CK_Generic: + break; + case CK_i386: + // The rest are coming from the i386 define above. + Builder.defineMacro("__tune_i386__"); + break; + case CK_i486: + case CK_WinChipC6: + case CK_WinChip2: + case CK_C3: + Builder.defineMacro("__i486"); + Builder.defineMacro("__i486__"); + Builder.defineMacro("__tune_i486__"); + break; + case CK_PentiumMMX: + Builder.defineMacro("__pentium_mmx__"); + Builder.defineMacro("__tune_pentium_mmx__"); + // Fallthrough + case CK_i586: + case CK_Pentium: + Builder.defineMacro("__i586"); + Builder.defineMacro("__i586__"); + Builder.defineMacro("__tune_i586__"); + Builder.defineMacro("__pentium"); + Builder.defineMacro("__pentium__"); + Builder.defineMacro("__tune_pentium__"); + break; + case CK_Pentium3: + case CK_Pentium3M: + case CK_PentiumM: + Builder.defineMacro("__tune_pentium3__"); + // Fallthrough + case CK_Pentium2: + case CK_C3_2: + Builder.defineMacro("__tune_pentium2__"); + // Fallthrough + case CK_PentiumPro: + Builder.defineMacro("__tune_i686__"); + Builder.defineMacro("__tune_pentiumpro__"); + // Fallthrough + case CK_i686: + Builder.defineMacro("__i686"); + Builder.defineMacro("__i686__"); + // Strangely, __tune_i686__ isn't defined by GCC when CPU == i686. + Builder.defineMacro("__pentiumpro"); + Builder.defineMacro("__pentiumpro__"); + break; + case CK_Pentium4: + case CK_Pentium4M: + Builder.defineMacro("__pentium4"); + Builder.defineMacro("__pentium4__"); + Builder.defineMacro("__tune_pentium4__"); + break; + case CK_Yonah: + case CK_Prescott: + case CK_Nocona: + Builder.defineMacro("__nocona"); + Builder.defineMacro("__nocona__"); + Builder.defineMacro("__tune_nocona__"); + break; + case CK_Core2: + case CK_Penryn: + Builder.defineMacro("__core2"); + Builder.defineMacro("__core2__"); + Builder.defineMacro("__tune_core2__"); + break; + case CK_Atom: + Builder.defineMacro("__atom"); + Builder.defineMacro("__atom__"); + Builder.defineMacro("__tune_atom__"); + break; + case CK_Corei7: + case CK_Corei7AVX: + case CK_CoreAVXi: + Builder.defineMacro("__corei7"); + Builder.defineMacro("__corei7__"); + Builder.defineMacro("__tune_corei7__"); + break; + case CK_K6_2: + Builder.defineMacro("__k6_2__"); + Builder.defineMacro("__tune_k6_2__"); + // Fallthrough + case CK_K6_3: + if (CPU != CK_K6_2) { // In case of fallthrough + // FIXME: GCC may be enabling these in cases where some other k6 + // architecture is specified but -m3dnow is explicitly provided. The + // exact semantics need to be determined and emulated here. + Builder.defineMacro("__k6_3__"); + Builder.defineMacro("__tune_k6_3__"); + } + // Fallthrough + case CK_K6: + Builder.defineMacro("__k6"); + Builder.defineMacro("__k6__"); + Builder.defineMacro("__tune_k6__"); + break; + case CK_Athlon: + case CK_AthlonThunderbird: + case CK_Athlon4: + case CK_AthlonXP: + case CK_AthlonMP: + Builder.defineMacro("__athlon"); + Builder.defineMacro("__athlon__"); + Builder.defineMacro("__tune_athlon__"); + if (SSELevel != NoSSE) { + Builder.defineMacro("__athlon_sse__"); + Builder.defineMacro("__tune_athlon_sse__"); + } + break; + case CK_K8: + case CK_K8SSE3: + case CK_x86_64: + case CK_Opteron: + case CK_OpteronSSE3: + case CK_Athlon64: + case CK_Athlon64SSE3: + case CK_AthlonFX: + Builder.defineMacro("__k8"); + Builder.defineMacro("__k8__"); + Builder.defineMacro("__tune_k8__"); + break; + case CK_Geode: + Builder.defineMacro("__geode"); + Builder.defineMacro("__geode__"); + Builder.defineMacro("__tune_geode__"); + break; + } // Target properties. Builder.defineMacro("__LITTLE_ENDIAN__"); - - // Subtarget options. - Builder.defineMacro("__nocona"); - Builder.defineMacro("__nocona__"); - Builder.defineMacro("__tune_nocona__"); Builder.defineMacro("__REGISTER_PREFIX__", ""); // Define __NO_MATH_INLINES on linux/x86 so that we don't get inline @@ -1396,6 +1842,12 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, // backend can't deal with (PR879). Builder.defineMacro("__NO_MATH_INLINES"); + if (HasAES) + Builder.defineMacro("__AES__"); + + if (HasAVX) + Builder.defineMacro("__AVX__"); + // Each case falls through to the previous one here. switch (SSELevel) { case SSE42: @@ -1416,20 +1868,20 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, break; } - if (Opts.Microsoft && PointerWidth == 32) { + if (Opts.MicrosoftExt && PointerWidth == 32) { switch (SSELevel) { case SSE42: case SSE41: case SSSE3: case SSE3: case SSE2: - Builder.defineMacro("_M_IX86_FP", llvm::Twine(2)); + Builder.defineMacro("_M_IX86_FP", Twine(2)); break; case SSE1: - Builder.defineMacro("_M_IX86_FP", llvm::Twine(1)); + Builder.defineMacro("_M_IX86_FP", Twine(1)); break; default: - Builder.defineMacro("_M_IX86_FP", llvm::Twine(0)); + Builder.defineMacro("_M_IX86_FP", Twine(0)); } } @@ -1523,7 +1975,7 @@ public: LongDoubleAlign = 32; DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" "i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-" - "a0:0:64-f80:32:32-n8:16:32"; + "a0:0:64-f80:32:32-n8:16:32-S128"; SizeType = UnsignedInt; PtrDiffType = SignedInt; IntPtrType = SignedInt; @@ -1533,6 +1985,11 @@ public: RealTypeUsesObjCFPRet = ((1 << TargetInfo::Float) | (1 << TargetInfo::Double) | (1 << TargetInfo::LongDouble)); + + // x86-32 has atomics up to 8 bytes + // FIXME: Check that we actually have cmpxchg8b before setting + // MaxAtomicInlineWidth. (cmpxchg8b is an i586 instruction.) + MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; } virtual const char *getVAListDeclaration() const { return "typedef char* __builtin_va_list;"; @@ -1569,7 +2026,7 @@ public: IntPtrType = SignedLong; DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" "i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-" - "a0:0:64-f80:128:128-n8:16:32"; + "a0:0:64-f80:128:128-n8:16:32-S128"; HasAlignMac68kSupport = true; } @@ -1587,7 +2044,7 @@ public: 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-f80:128:128-v64:64:64-" - "v128:128:128-a0:0:64-f80:32:32-n8:16:32"; + "v128:128:128-a0:0:64-f80:32:32-n8:16:32-S32"; } virtual void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { @@ -1636,7 +2093,7 @@ public: // mingw32-gcc provides __declspec(a) as alias of __attribute__((a)). // In contrast, clang-cc1 provides __declspec(a) with -fms-extensions. - if (Opts.Microsoft) + if (Opts.MicrosoftExt) // Provide "as-is" __declspec. Builder.defineMacro("__declspec", "__declspec"); else @@ -1657,7 +2114,7 @@ public: 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-n8:16:32"; + "a0:0:64-f80:32:32-n8:16:32-S32"; } virtual void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { @@ -1699,9 +2156,6 @@ protected: MacroBuilder &Builder) const { // RTEMS defines; list based off of gcc output - // FIXME: Move version number handling to llvm::Triple. - llvm::StringRef Release = Triple.getOSName().substr(strlen("rtems"), 1); - Builder.defineMacro("__rtems__"); Builder.defineMacro("__ELF__"); } @@ -1767,10 +2221,16 @@ public: DescriptionString = "e-p:64:64:64-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-s0:64:64-f80:128:128-n8:16:32:64"; + "a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"; // Use fpret only for long double. RealTypeUsesObjCFPRet = (1 << TargetInfo::LongDouble); + + // x86-64 has atomics up to 16 bytes. + // FIXME: Once the backend is fixed, increase MaxAtomicInlineWidth to 128 + // on CPUs with cmpxchg16b + MaxAtomicPromoteWidth = 128; + MaxAtomicInlineWidth = 64; } virtual const char *getVAListDeclaration() const { return "typedef struct __va_list_tag {" @@ -1855,7 +2315,7 @@ public: // mingw32-gcc provides __declspec(a) as alias of __attribute__((a)). // In contrast, clang-cc1 provides __declspec(a) with -fms-extensions. - if (Opts.Microsoft) + if (Opts.MicrosoftExt) // Provide "as-is" __declspec. Builder.defineMacro("__declspec", "__declspec"); else @@ -1934,15 +2394,19 @@ public: // 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:64:128-a0:0:32-n32"); + "v64:64:64-v128:64:128-a0:0:32-n32-S64"); } 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:64:128-a0:0:64-n32"); + "v64:64:64-v128:64:128-a0:0:64-n32-S64"); } // ARM targets default to using the ARM C++ ABI. CXXABI = CXXABI_ARM; + + // ARM has atomics up to 8 bytes + // FIXME: Set MaxAtomicInlineWidth if we have the feature v6e + MaxAtomicPromoteWidth = 64; } virtual const char *getABI() const { return ABI.c_str(); } virtual bool setABI(const std::string &Name) { @@ -1960,16 +2424,27 @@ public: // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc. UseBitFieldTypeAlignment = false; + /// Do force alignment of members that follow zero length bitfields. If + /// the alignment of the zero-length bitfield is greater than the member + /// that follows it, `bar', `bar' will be aligned as the type of the + /// zero length bitfield. + UseZeroLengthBitfieldAlignment = true; + + /// gcc forces the alignment to 4 bytes, regardless of the type of the + /// zero length bitfield. This corresponds to EMPTY_FIELD_BOUNDARY in + /// gcc. + ZeroLengthBitfieldBoundary = 32; + 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:64-f32:32:32-f64:32:64-" - "v64:32:64-v128:32:128-a0:0:32-n32"); + "v64:32:64-v128:32:128-a0:0:32-n32-S32"); } else { DescriptionString = ("e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" "i64:32:64-f32:32:32-f64:32:64-" - "v64:32:64-v128:32:128-a0:0:32-n32"); + "v64:32:64-v128:32:128-a0:0:32-n32-S32"); } // FIXME: Override "preferred align" for double and long long. @@ -1983,8 +2458,7 @@ public: return true; } - void getDefaultFeatures(const std::string &CPU, - llvm::StringMap<bool> &Features) const { + void getDefaultFeatures(llvm::StringMap<bool> &Features) const { if (CPU == "arm1136jf-s" || CPU == "arm1176jzf-s" || CPU == "mpcore") Features["vfp2"] = true; else if (CPU == "cortex-a8" || CPU == "cortex-a9") @@ -2029,7 +2503,7 @@ public: Features.erase(it); } - static const char *getCPUDefineSuffix(llvm::StringRef Name) { + static const char *getCPUDefineSuffix(StringRef Name) { return llvm::StringSwitch<const char*>(Name) .Cases("arm8", "arm810", "4") .Cases("strongarm", "strongarm110", "strongarm1100", "strongarm1110", "4") @@ -2068,7 +2542,7 @@ public: Builder.defineMacro("__LITTLE_ENDIAN__"); Builder.defineMacro("__REGISTER_PREFIX__", ""); - llvm::StringRef CPUArch = getCPUDefineSuffix(CPU); + StringRef CPUArch = getCPUDefineSuffix(CPU); Builder.defineMacro("__ARM_ARCH_" + CPUArch + "__"); // Subtarget options. @@ -2131,6 +2605,9 @@ public: case 'P': // VFP Floating point register double precision Info.setAllowsRegister(); return true; + case 'Q': // A memory address that is a single base register. + Info.setAllowsMemory(); + return true; case 'U': // a memory reference... switch (Name[1]) { case 'q': // ...ARMV4 ldrsb @@ -2247,6 +2724,9 @@ public: DarwinARMTargetInfo(const std::string& triple) : DarwinTargetInfo<ARMTargetInfo>(triple) { HasAlignMac68kSupport = true; + // iOS always has 64-bit atomic instructions. + // FIXME: This should be based off of the target features in ARMTargetInfo. + MaxAtomicInlineWidth = 64; } }; } // end anonymous namespace. @@ -2592,6 +3072,12 @@ namespace { // target processor and program binary. TCE co-design environment is // publicly available in http://tce.cs.tut.fi + static const unsigned TCEOpenCLAddrSpaceMap[] = { + 3, // opencl_global + 4, // opencl_local + 5 // opencl_constant + }; + class TCETargetInfo : public TargetInfo{ public: TCETargetInfo(const std::string& triple) : TargetInfo(triple) { @@ -2620,6 +3106,7 @@ namespace { "i16:16:32-i32:32:32-i64:32:32-" "f32:32:32-f64:32:32-v64:32:32-" "v128:32:32-a0:0:32-n32"; + AddrSpaceMap = &TCEOpenCLAddrSpaceMap; } virtual void getTargetDefines(const LangOptions &Opts, @@ -2648,51 +3135,30 @@ namespace { } namespace { -class MipsTargetInfo : public TargetInfo { - std::string ABI, CPU; - static const TargetInfo::GCCRegAlias GCCRegAliases[]; - static const char * const GCCRegNames[]; +class MipsTargetInfoBase : public TargetInfo { + std::string CPU; +protected: + std::string ABI; public: - MipsTargetInfo(const std::string& triple) : TargetInfo(triple), ABI("o32") { - DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32"; + MipsTargetInfoBase(const std::string& triple, const std::string& ABIStr) + : TargetInfo(triple), ABI(ABIStr) { SizeType = UnsignedInt; PtrDiffType = SignedInt; } virtual const char *getABI() const { return ABI.c_str(); } - virtual bool setABI(const std::string &Name) { - - if ((Name == "o32") || (Name == "eabi")) { - ABI = Name; - return true; - } else - return false; - } + virtual bool setABI(const std::string &Name) = 0; virtual bool setCPU(const std::string &Name) { CPU = Name; return true; } - void getDefaultFeatures(const std::string &CPU, - llvm::StringMap<bool> &Features) const { + void getDefaultFeatures(llvm::StringMap<bool> &Features) const { Features[ABI] = true; Features[CPU] = true; } virtual void getArchDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { - if (ABI == "o32") - Builder.defineMacro("__mips_o32"); - else if (ABI == "eabi") - Builder.defineMacro("__mips_eabi"); - } + MacroBuilder &Builder) const = 0; virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { - DefineStd(Builder, "mips", Opts); - Builder.defineMacro("_mips"); - DefineStd(Builder, "MIPSEB", Opts); - Builder.defineMacro("_MIPSEB"); - Builder.defineMacro("__REGISTER_PREFIX__", ""); - getArchDefines(Opts, Builder); - } + MacroBuilder &Builder) const = 0; virtual void getTargetBuiltins(const Builtin::Info *&Records, unsigned &NumRecords) const { // FIXME: Implement! @@ -2701,9 +3167,24 @@ public: return "typedef void* __builtin_va_list;"; } virtual void getGCCRegNames(const char * const *&Names, - unsigned &NumNames) const; + unsigned &NumNames) const { + static const char * const 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", "$sp", "$fp", "$31", + "$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", + "hi", "lo", "", "$fcc0","$fcc1","$fcc2","$fcc3","$fcc4", + "$fcc5","$fcc6","$fcc7" + }; + Names = GCCRegNames; + NumNames = llvm::array_lengthof(GCCRegNames); + } virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const; + unsigned &NumAliases) const = 0; virtual bool validateAsmConstraint(const char *&Name, TargetInfo::ConstraintInfo &Info) const { switch (*Name) { @@ -2724,89 +3205,296 @@ public: } }; -const char * const MipsTargetInfo::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", "$sp", "$fp", "$31", - "$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", - "hi", "lo", "", "$fcc0","$fcc1","$fcc2","$fcc3","$fcc4", - "$fcc5","$fcc6","$fcc7" +class Mips32TargetInfoBase : public MipsTargetInfoBase { +public: + Mips32TargetInfoBase(const std::string& triple) : + MipsTargetInfoBase(triple, "o32") {} + virtual bool setABI(const std::string &Name) { + if ((Name == "o32") || (Name == "eabi")) { + ABI = Name; + return true; + } else + return false; + } + virtual void getArchDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + if (ABI == "o32") { + Builder.defineMacro("__mips_o32"); + Builder.defineMacro("_ABIO32", "1"); + Builder.defineMacro("_MIPS_SIM", "_ABIO32"); + } + else if (ABI == "eabi") + Builder.defineMacro("__mips_eabi"); + else + llvm_unreachable("Invalid ABI for Mips32."); + } + virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const { + static const TargetInfo::GCCRegAlias GCCRegAliases[] = { + { { "at" }, "$1" }, + { { "v0" }, "$2" }, + { { "v1" }, "$3" }, + { { "a0" }, "$4" }, + { { "a1" }, "$5" }, + { { "a2" }, "$6" }, + { { "a3" }, "$7" }, + { { "t0" }, "$8" }, + { { "t1" }, "$9" }, + { { "t2" }, "$10" }, + { { "t3" }, "$11" }, + { { "t4" }, "$12" }, + { { "t5" }, "$13" }, + { { "t6" }, "$14" }, + { { "t7" }, "$15" }, + { { "s0" }, "$16" }, + { { "s1" }, "$17" }, + { { "s2" }, "$18" }, + { { "s3" }, "$19" }, + { { "s4" }, "$20" }, + { { "s5" }, "$21" }, + { { "s6" }, "$22" }, + { { "s7" }, "$23" }, + { { "t8" }, "$24" }, + { { "t9" }, "$25" }, + { { "k0" }, "$26" }, + { { "k1" }, "$27" }, + { { "gp" }, "$28" }, + { { "sp" }, "$29" }, + { { "fp" }, "$30" }, + { { "ra" }, "$31" } + }; + Aliases = GCCRegAliases; + NumAliases = llvm::array_lengthof(GCCRegAliases); + } }; -void MipsTargetInfo::getGCCRegNames(const char * const *&Names, - unsigned &NumNames) const { - Names = GCCRegNames; - NumNames = llvm::array_lengthof(GCCRegNames); -} +class Mips32EBTargetInfo : public Mips32TargetInfoBase { +public: + Mips32EBTargetInfo(const std::string& triple) : Mips32TargetInfoBase(triple) { + DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" + "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32"; + } + virtual void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + DefineStd(Builder, "mips", Opts); + Builder.defineMacro("_mips"); + DefineStd(Builder, "MIPSEB", Opts); + Builder.defineMacro("_MIPSEB"); + Builder.defineMacro("__REGISTER_PREFIX__", ""); + getArchDefines(Opts, Builder); + } +}; -const TargetInfo::GCCRegAlias MipsTargetInfo::GCCRegAliases[] = { - { { "at" }, "$1" }, - { { "v0" }, "$2" }, - { { "v1" }, "$3" }, - { { "a0" }, "$4" }, - { { "a1" }, "$5" }, - { { "a2" }, "$6" }, - { { "a3" }, "$7" }, - { { "t0" }, "$8" }, - { { "t1" }, "$9" }, - { { "t2" }, "$10" }, - { { "t3" }, "$11" }, - { { "t4" }, "$12" }, - { { "t5" }, "$13" }, - { { "t6" }, "$14" }, - { { "t7" }, "$15" }, - { { "s0" }, "$16" }, - { { "s1" }, "$17" }, - { { "s2" }, "$18" }, - { { "s3" }, "$19" }, - { { "s4" }, "$20" }, - { { "s5" }, "$21" }, - { { "s6" }, "$22" }, - { { "s7" }, "$23" }, - { { "t8" }, "$24" }, - { { "t9" }, "$25" }, - { { "k0" }, "$26" }, - { { "k1" }, "$27" }, - { { "gp" }, "$28" }, - { { "sp" }, "$29" }, - { { "fp" }, "$30" }, - { { "ra" }, "$31" } +class Mips32ELTargetInfo : public Mips32TargetInfoBase { +public: + Mips32ELTargetInfo(const std::string& triple) : Mips32TargetInfoBase(triple) { + DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" + "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32"; + } + virtual void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + DefineStd(Builder, "mips", Opts); + Builder.defineMacro("_mips"); + DefineStd(Builder, "MIPSEL", Opts); + Builder.defineMacro("_MIPSEL"); + Builder.defineMacro("__REGISTER_PREFIX__", ""); + getArchDefines(Opts, Builder); + } }; -void MipsTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const { - Aliases = GCCRegAliases; - NumAliases = llvm::array_lengthof(GCCRegAliases); -} +class Mips64TargetInfoBase : public MipsTargetInfoBase { + virtual void SetDescriptionString(const std::string &Name) = 0; +public: + Mips64TargetInfoBase(const std::string& triple) : + MipsTargetInfoBase(triple, "n64") {} + virtual bool setABI(const std::string &Name) { + SetDescriptionString(Name); + if ((Name == "n32") || (Name == "n64")) { + ABI = Name; + return true; + } else + return false; + } + virtual void getArchDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + if (ABI == "n32") { + Builder.defineMacro("__mips_n32"); + Builder.defineMacro("_ABIN32", "2"); + Builder.defineMacro("_MIPS_SIM", "_ABIN32"); + } + else if (ABI == "n64") { + Builder.defineMacro("__mips_n64"); + Builder.defineMacro("_ABI64", "3"); + Builder.defineMacro("_MIPS_SIM", "_ABI64"); + } + else + llvm_unreachable("Invalid ABI for Mips64."); + } + virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const { + static const TargetInfo::GCCRegAlias GCCRegAliases[] = { + { { "at" }, "$1" }, + { { "v0" }, "$2" }, + { { "v1" }, "$3" }, + { { "a0" }, "$4" }, + { { "a1" }, "$5" }, + { { "a2" }, "$6" }, + { { "a3" }, "$7" }, + { { "a4" }, "$8" }, + { { "a5" }, "$9" }, + { { "a6" }, "$10" }, + { { "a7" }, "$11" }, + { { "t0" }, "$12" }, + { { "t1" }, "$13" }, + { { "t2" }, "$14" }, + { { "t3" }, "$15" }, + { { "s0" }, "$16" }, + { { "s1" }, "$17" }, + { { "s2" }, "$18" }, + { { "s3" }, "$19" }, + { { "s4" }, "$20" }, + { { "s5" }, "$21" }, + { { "s6" }, "$22" }, + { { "s7" }, "$23" }, + { { "t8" }, "$24" }, + { { "t9" }, "$25" }, + { { "k0" }, "$26" }, + { { "k1" }, "$27" }, + { { "gp" }, "$28" }, + { { "sp" }, "$29" }, + { { "fp" }, "$30" }, + { { "ra" }, "$31" } + }; + Aliases = GCCRegAliases; + NumAliases = llvm::array_lengthof(GCCRegAliases); + } +}; + +class Mips64EBTargetInfo : public Mips64TargetInfoBase { + virtual void SetDescriptionString(const std::string &Name) { + // Change DescriptionString only if ABI is n32. + if (Name == "n32") + DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" + "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32"; + } +public: + Mips64EBTargetInfo(const std::string& triple) : Mips64TargetInfoBase(triple) { + // Default ABI is n64. + DescriptionString = "E-p:64:64:64-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" + "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32"; + } + virtual void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + DefineStd(Builder, "mips", Opts); + Builder.defineMacro("_mips"); + DefineStd(Builder, "MIPSEB", Opts); + Builder.defineMacro("_MIPSEB"); + Builder.defineMacro("__REGISTER_PREFIX__", ""); + getArchDefines(Opts, Builder); + } +}; + +class Mips64ELTargetInfo : public Mips64TargetInfoBase { + virtual void SetDescriptionString(const std::string &Name) { + // Change DescriptionString only if ABI is n32. + if (Name == "n32") + DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" + "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32"; + } +public: + Mips64ELTargetInfo(const std::string& triple) : Mips64TargetInfoBase(triple) { + // Default ABI is n64. + DescriptionString = "e-p:64:64:64-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" + "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32"; + } + virtual void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + DefineStd(Builder, "mips", Opts); + Builder.defineMacro("_mips"); + DefineStd(Builder, "MIPSEL", Opts); + Builder.defineMacro("_MIPSEL"); + Builder.defineMacro("__REGISTER_PREFIX__", ""); + getArchDefines(Opts, Builder); + } +}; } // end anonymous namespace. namespace { -class MipselTargetInfo : public MipsTargetInfo { +class PNaClTargetInfo : public TargetInfo { public: - MipselTargetInfo(const std::string& triple) : MipsTargetInfo(triple) { - DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32"; + PNaClTargetInfo(const std::string& triple) : TargetInfo(triple) { + this->UserLabelPrefix = ""; + this->LongAlign = 32; + this->LongWidth = 32; + this->PointerAlign = 32; + this->PointerWidth = 32; + this->IntMaxType = TargetInfo::SignedLongLong; + this->UIntMaxType = TargetInfo::UnsignedLongLong; + this->Int64Type = TargetInfo::SignedLongLong; + this->DoubleAlign = 64; + this->LongDoubleWidth = 64; + this->LongDoubleAlign = 64; + this->SizeType = TargetInfo::UnsignedInt; + this->PtrDiffType = TargetInfo::SignedInt; + this->IntPtrType = TargetInfo::SignedInt; + this->RegParmMax = 2; + DescriptionString = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-" + "f32:32:32-f64:64:64-p:32:32:32-v128:32:32"; } + void getDefaultFeatures(llvm::StringMap<bool> &Features) const { + } + virtual void getArchDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + Builder.defineMacro("__le32__"); + Builder.defineMacro("__pnacl__"); + } virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const; + MacroBuilder &Builder) const { + DefineStd(Builder, "unix", Opts); + Builder.defineMacro("__ELF__"); + if (Opts.POSIXThreads) + Builder.defineMacro("_REENTRANT"); + if (Opts.CPlusPlus) + Builder.defineMacro("_GNU_SOURCE"); + + Builder.defineMacro("__native_client__"); + getArchDefines(Opts, Builder); + } + virtual void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const { + } + virtual const char *getVAListDeclaration() const { + return "typedef int __builtin_va_list[4];"; + } + virtual void getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const; + virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const; + virtual bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &Info) const { + return false; + } + + virtual const char *getClobbers() const { + return ""; + } }; -void MipselTargetInfo::getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { - DefineStd(Builder, "mips", Opts); - Builder.defineMacro("_mips"); - DefineStd(Builder, "MIPSEL", Opts); - Builder.defineMacro("_MIPSEL"); - Builder.defineMacro("__REGISTER_PREFIX__", ""); - getArchDefines(Opts, Builder); +void PNaClTargetInfo::getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const { + Names = NULL; + NumNames = 0; +} + +void PNaClTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const { + Aliases = NULL; + NumAliases = 0; } } // end anonymous namespace. + //===----------------------------------------------------------------------===// // Driver code //===----------------------------------------------------------------------===// @@ -2847,40 +3535,74 @@ static TargetInfo *AllocateTarget(const std::string &T) { case llvm::Triple::mips: switch (os) { - case llvm::Triple::Psp: - return new PSPTargetInfo<MipsTargetInfo>(T); case llvm::Triple::Linux: - return new LinuxTargetInfo<MipsTargetInfo>(T); + return new LinuxTargetInfo<Mips32EBTargetInfo>(T); case llvm::Triple::RTEMS: - return new RTEMSTargetInfo<MipsTargetInfo>(T); + return new RTEMSTargetInfo<Mips32EBTargetInfo>(T); case llvm::Triple::FreeBSD: - return new FreeBSDTargetInfo<MipsTargetInfo>(T); + return new FreeBSDTargetInfo<Mips32EBTargetInfo>(T); case llvm::Triple::NetBSD: - return new NetBSDTargetInfo<MipsTargetInfo>(T); + return new NetBSDTargetInfo<Mips32EBTargetInfo>(T); default: - return new MipsTargetInfo(T); + return new Mips32EBTargetInfo(T); } case llvm::Triple::mipsel: switch (os) { - case llvm::Triple::Psp: - return new PSPTargetInfo<MipselTargetInfo>(T); case llvm::Triple::Linux: - return new LinuxTargetInfo<MipselTargetInfo>(T); + return new LinuxTargetInfo<Mips32ELTargetInfo>(T); case llvm::Triple::RTEMS: - return new RTEMSTargetInfo<MipselTargetInfo>(T); + return new RTEMSTargetInfo<Mips32ELTargetInfo>(T); case llvm::Triple::FreeBSD: - return new FreeBSDTargetInfo<MipselTargetInfo>(T); + return new FreeBSDTargetInfo<Mips32ELTargetInfo>(T); case llvm::Triple::NetBSD: - return new NetBSDTargetInfo<MipselTargetInfo>(T); + return new NetBSDTargetInfo<Mips32ELTargetInfo>(T); default: - return new MipsTargetInfo(T); + return new Mips32ELTargetInfo(T); + } + + case llvm::Triple::mips64: + switch (os) { + case llvm::Triple::Linux: + return new LinuxTargetInfo<Mips64EBTargetInfo>(T); + case llvm::Triple::RTEMS: + return new RTEMSTargetInfo<Mips64EBTargetInfo>(T); + case llvm::Triple::FreeBSD: + return new FreeBSDTargetInfo<Mips64EBTargetInfo>(T); + case llvm::Triple::NetBSD: + return new NetBSDTargetInfo<Mips64EBTargetInfo>(T); + default: + return new Mips64EBTargetInfo(T); + } + + case llvm::Triple::mips64el: + switch (os) { + case llvm::Triple::Linux: + return new LinuxTargetInfo<Mips64ELTargetInfo>(T); + case llvm::Triple::RTEMS: + return new RTEMSTargetInfo<Mips64ELTargetInfo>(T); + case llvm::Triple::FreeBSD: + return new FreeBSDTargetInfo<Mips64ELTargetInfo>(T); + case llvm::Triple::NetBSD: + return new NetBSDTargetInfo<Mips64ELTargetInfo>(T); + default: + return new Mips64ELTargetInfo(T); + } + + case llvm::Triple::le32: + switch (os) { + case llvm::Triple::NativeClient: + return new PNaClTargetInfo(T); + default: + return NULL; } case llvm::Triple::ppc: if (Triple.isOSDarwin()) return new DarwinPPC32TargetInfo(T); switch (os) { + case llvm::Triple::Linux: + return new LinuxTargetInfo<PPC32TargetInfo>(T); case llvm::Triple::FreeBSD: return new FreeBSDTargetInfo<PPC32TargetInfo>(T); case llvm::Triple::NetBSD: @@ -2895,6 +3617,8 @@ static TargetInfo *AllocateTarget(const std::string &T) { if (Triple.isOSDarwin()) return new DarwinPPC64TargetInfo(T); switch (os) { + case llvm::Triple::Linux: + return new LinuxTargetInfo<PPC64TargetInfo>(T); case llvm::Triple::Lv2: return new PS3PPUTargetInfo<PPC64TargetInfo>(T); case llvm::Triple::FreeBSD: @@ -2915,6 +3639,8 @@ static TargetInfo *AllocateTarget(const std::string &T) { case llvm::Triple::sparc: switch (os) { + case llvm::Triple::Linux: + return new LinuxTargetInfo<SparcV8TargetInfo>(T); case llvm::Triple::AuroraUX: return new AuroraUXSparcV8TargetInfo(T); case llvm::Triple::Solaris: @@ -3003,7 +3729,7 @@ static TargetInfo *AllocateTarget(const std::string &T) { /// CreateTargetInfo - Return the target info object for the specified target /// triple. -TargetInfo *TargetInfo::CreateTargetInfo(Diagnostic &Diags, +TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, TargetOptions &Opts) { llvm::Triple Triple(Opts.Triple); @@ -3035,7 +3761,7 @@ TargetInfo *TargetInfo::CreateTargetInfo(Diagnostic &Diags, // Compute the default target features, we need the target to handle this // because features may have dependencies on one another. llvm::StringMap<bool> Features; - Target->getDefaultFeatures(Opts.CPU, Features); + Target->getDefaultFeatures(Features); // Apply the user specified deltas. for (std::vector<std::string>::const_iterator it = Opts.Features.begin(), diff --git a/contrib/llvm/tools/clang/lib/Basic/Version.cpp b/contrib/llvm/tools/clang/lib/Basic/Version.cpp index 89076ca..390a685 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Version.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Version.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Basic/Version.h" +#include "clang/Basic/LLVM.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Config/config.h" #include <cstring> @@ -24,14 +25,14 @@ std::string getClangRepositoryPath() { return CLANG_REPOSITORY_STRING; #else #ifdef SVN_REPOSITORY - llvm::StringRef URL(SVN_REPOSITORY); + StringRef URL(SVN_REPOSITORY); #else - llvm::StringRef URL(""); + StringRef URL(""); #endif // If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us // pick up a tag in an SVN export, for example. - static llvm::StringRef SVNRepository("$URL: http://llvm.org/svn/llvm-project/cfe/trunk/lib/Basic/Version.cpp $"); + static StringRef SVNRepository("$URL: http://llvm.org/svn/llvm-project/cfe/branches/release_30/lib/Basic/Version.cpp $"); if (URL.empty()) { URL = SVNRepository.slice(SVNRepository.find(':'), SVNRepository.find("/lib/Basic")); @@ -42,7 +43,7 @@ std::string getClangRepositoryPath() { // Trim path prefix off, assuming path came from standard cfe path. size_t Start = URL.find("cfe/"); - if (Start != llvm::StringRef::npos) + if (Start != StringRef::npos) URL = URL.substr(Start + 4); return URL; diff --git a/contrib/llvm/tools/clang/lib/Basic/VersionTuple.cpp b/contrib/llvm/tools/clang/lib/Basic/VersionTuple.cpp index d5cf126..77aad39 100644 --- a/contrib/llvm/tools/clang/lib/Basic/VersionTuple.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/VersionTuple.cpp @@ -25,7 +25,7 @@ std::string VersionTuple::getAsString() const { return Result; } -llvm::raw_ostream& clang::operator<<(llvm::raw_ostream &Out, +raw_ostream& clang::operator<<(raw_ostream &Out, const VersionTuple &V) { Out << V.getMajor(); if (llvm::Optional<unsigned> Minor = V.getMinor()) |