summaryrefslogtreecommitdiff
path: root/lib/Frontend/PCHReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Frontend/PCHReader.cpp')
-rw-r--r--lib/Frontend/PCHReader.cpp186
1 files changed, 80 insertions, 106 deletions
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 26f426ba329b7..ca7aa3260c62f 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -13,6 +13,7 @@
#include "clang/Frontend/PCHReader.h"
#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/Utils.h"
#include "../Sema/Sema.h" // FIXME: move Sema headers elsewhere
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
@@ -104,6 +105,7 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) {
PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
PARSE_LANGOPT_IMPORTANT(AccessControl, diag::warn_pch_access_control);
PARSE_LANGOPT_IMPORTANT(CharIsSigned, diag::warn_pch_char_signed);
+ PARSE_LANGOPT_IMPORTANT(ShortWChar, diag::warn_pch_short_wchar);
if ((PPLangOpts.getGCMode() != 0) != (LangOpts.getGCMode() != 0)) {
Reader.Diag(diag::warn_pch_gc_mode)
<< LangOpts.getGCMode() << PPLangOpts.getGCMode();
@@ -121,83 +123,56 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) {
return false;
}
-bool PCHValidator::ReadTargetTriple(const std::string &Triple) {
- if (Triple != PP.getTargetInfo().getTriple().getTriple()) {
- Reader.Diag(diag::warn_pch_target_triple)
- << Triple << PP.getTargetInfo().getTriple().getTriple();
- return true;
- }
- return false;
-}
-
-/// \brief Split the given string into a vector of lines, eliminating
-/// any empty lines in the process.
-///
-/// \param Str the string to split.
-/// \param Len the length of Str.
-/// \param KeepEmptyLines true if empty lines should be included
-/// \returns a vector of lines, with the line endings removed
-static std::vector<std::string> splitLines(const char *Str, unsigned Len,
- bool KeepEmptyLines = false) {
- std::vector<std::string> Lines;
- for (unsigned LineStart = 0; LineStart < Len; ++LineStart) {
- unsigned LineEnd = LineStart;
- while (LineEnd < Len && Str[LineEnd] != '\n')
- ++LineEnd;
- if (LineStart != LineEnd || KeepEmptyLines)
- Lines.push_back(std::string(&Str[LineStart], &Str[LineEnd]));
- LineStart = LineEnd;
- }
- return Lines;
-}
-
-/// \brief Determine whether the string Haystack starts with the
-/// substring Needle.
-static bool startsWith(const std::string &Haystack, const char *Needle) {
- for (unsigned I = 0, N = Haystack.size(); Needle[I] != 0; ++I) {
- if (I == N)
- return false;
- if (Haystack[I] != Needle[I])
- return false;
- }
+bool PCHValidator::ReadTargetTriple(llvm::StringRef Triple) {
+ if (Triple == PP.getTargetInfo().getTriple().str())
+ return false;
+ Reader.Diag(diag::warn_pch_target_triple)
+ << Triple << PP.getTargetInfo().getTriple().str();
return true;
}
-/// \brief Determine whether the string Haystack starts with the
-/// substring Needle.
-static inline bool startsWith(const std::string &Haystack,
- const std::string &Needle) {
- return startsWith(Haystack, Needle.c_str());
-}
-
-bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
- unsigned PCHPredefLen,
+bool PCHValidator::ReadPredefinesBuffer(llvm::StringRef PCHPredef,
FileID PCHBufferID,
+ llvm::StringRef OriginalFileName,
std::string &SuggestedPredefines) {
- const char *Predef = PP.getPredefines().c_str();
- unsigned PredefLen = PP.getPredefines().size();
-
- // If the two predefines buffers compare equal, we're done!
- if (PredefLen == PCHPredefLen &&
- strncmp(Predef, PCHPredef, PCHPredefLen) == 0)
+ // We are in the context of an implicit include, so the predefines buffer will
+ // have a #include entry for the PCH file itself (as normalized by the
+ // preprocessor initialization). Find it and skip over it in the checking
+ // below.
+ llvm::SmallString<256> PCHInclude;
+ PCHInclude += "#include \"";
+ PCHInclude += NormalizeDashIncludePath(OriginalFileName);
+ PCHInclude += "\"\n";
+ std::pair<llvm::StringRef,llvm::StringRef> Split =
+ llvm::StringRef(PP.getPredefines()).split(PCHInclude.str());
+ llvm::StringRef Left = Split.first, Right = Split.second;
+ assert(Left != PP.getPredefines() && "Missing PCH include entry!");
+
+ // If the predefines is equal to the joined left and right halves, we're done!
+ if (Left.size() + Right.size() == PCHPredef.size() &&
+ PCHPredef.startswith(Left) && PCHPredef.endswith(Right))
return false;
SourceManager &SourceMgr = PP.getSourceManager();
- // The predefines buffers are different. Determine what the
- // differences are, and whether they require us to reject the PCH
- // file.
- std::vector<std::string> CmdLineLines = splitLines(Predef, PredefLen);
- std::vector<std::string> PCHLines = splitLines(PCHPredef, PCHPredefLen);
+ // The predefines buffers are different. Determine what the differences are,
+ // and whether they require us to reject the PCH file.
+ llvm::SmallVector<llvm::StringRef, 8> PCHLines;
+ PCHPredef.split(PCHLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+
+ llvm::SmallVector<llvm::StringRef, 8> CmdLineLines;
+ Left.split(CmdLineLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+ Right.split(CmdLineLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
- // Sort both sets of predefined buffer lines, since
+ // Sort both sets of predefined buffer lines, since we allow some extra
+ // definitions and they may appear at any point in the output.
std::sort(CmdLineLines.begin(), CmdLineLines.end());
std::sort(PCHLines.begin(), PCHLines.end());
- // Determine which predefines that where used to build the PCH file
- // are missing from the command line.
- std::vector<std::string> MissingPredefines;
+ // Determine which predefines that were used to build the PCH file are missing
+ // from the command line.
+ std::vector<llvm::StringRef> MissingPredefines;
std::set_difference(PCHLines.begin(), PCHLines.end(),
CmdLineLines.begin(), CmdLineLines.end(),
std::back_inserter(MissingPredefines));
@@ -205,31 +180,30 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
bool MissingDefines = false;
bool ConflictingDefines = false;
for (unsigned I = 0, N = MissingPredefines.size(); I != N; ++I) {
- const std::string &Missing = MissingPredefines[I];
- if (!startsWith(Missing, "#define ") != 0) {
+ llvm::StringRef Missing = MissingPredefines[I];
+ if (!Missing.startswith("#define ")) {
Reader.Diag(diag::warn_pch_compiler_options_mismatch);
return true;
}
- // This is a macro definition. Determine the name of the macro
- // we're defining.
+ // This is a macro definition. Determine the name of the macro we're
+ // defining.
std::string::size_type StartOfMacroName = strlen("#define ");
std::string::size_type EndOfMacroName
= Missing.find_first_of("( \n\r", StartOfMacroName);
assert(EndOfMacroName != std::string::npos &&
"Couldn't find the end of the macro name");
- std::string MacroName = Missing.substr(StartOfMacroName,
- EndOfMacroName - StartOfMacroName);
+ llvm::StringRef MacroName = Missing.slice(StartOfMacroName, EndOfMacroName);
- // Determine whether this macro was given a different definition
- // on the command line.
- std::string MacroDefStart = "#define " + MacroName;
+ // Determine whether this macro was given a different definition on the
+ // command line.
+ std::string MacroDefStart = "#define " + MacroName.str();
std::string::size_type MacroDefLen = MacroDefStart.size();
- std::vector<std::string>::iterator ConflictPos
+ llvm::SmallVector<llvm::StringRef, 8>::iterator ConflictPos
= std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(),
MacroDefStart);
for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) {
- if (!startsWith(*ConflictPos, MacroDefStart)) {
+ if (!ConflictPos->startswith(MacroDefStart)) {
// Different macro; we're done.
ConflictPos = CmdLineLines.end();
break;
@@ -250,21 +224,18 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
<< MacroName;
// Show the definition of this macro within the PCH file.
- const char *MissingDef = strstr(PCHPredef, Missing.c_str());
- unsigned Offset = MissingDef - PCHPredef;
- SourceLocation PCHMissingLoc
- = SourceMgr.getLocForStartOfFile(PCHBufferID)
- .getFileLocWithOffset(Offset);
- Reader.Diag(PCHMissingLoc, diag::note_pch_macro_defined_as)
- << MacroName;
+ llvm::StringRef::size_type Offset = PCHPredef.find(Missing);
+ assert(Offset != llvm::StringRef::npos && "Unable to find macro!");
+ SourceLocation PCHMissingLoc = SourceMgr.getLocForStartOfFile(PCHBufferID)
+ .getFileLocWithOffset(Offset);
+ Reader.Diag(PCHMissingLoc, diag::note_pch_macro_defined_as) << MacroName;
ConflictingDefines = true;
continue;
}
- // If the macro doesn't conflict, then we'll just pick up the
- // macro definition from the PCH file. Warn the user that they
- // made a mistake.
+ // If the macro doesn't conflict, then we'll just pick up the macro
+ // definition from the PCH file. Warn the user that they made a mistake.
if (ConflictingDefines)
continue; // Don't complain if there are already conflicting defs
@@ -274,10 +245,9 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
}
// Show the definition of this macro within the PCH file.
- const char *MissingDef = strstr(PCHPredef, Missing.c_str());
- unsigned Offset = MissingDef - PCHPredef;
- SourceLocation PCHMissingLoc
- = SourceMgr.getLocForStartOfFile(PCHBufferID)
+ llvm::StringRef::size_type Offset = PCHPredef.find(Missing);
+ assert(Offset != llvm::StringRef::npos && "Unable to find macro!");
+ SourceLocation PCHMissingLoc = SourceMgr.getLocForStartOfFile(PCHBufferID)
.getFileLocWithOffset(Offset);
Reader.Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch);
}
@@ -289,13 +259,13 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
// parameters that were not present when building the PCH
// file. Extra #defines are okay, so long as the identifiers being
// defined were not used within the precompiled header.
- std::vector<std::string> ExtraPredefines;
+ std::vector<llvm::StringRef> ExtraPredefines;
std::set_difference(CmdLineLines.begin(), CmdLineLines.end(),
PCHLines.begin(), PCHLines.end(),
std::back_inserter(ExtraPredefines));
for (unsigned I = 0, N = ExtraPredefines.size(); I != N; ++I) {
- const std::string &Extra = ExtraPredefines[I];
- if (!startsWith(Extra, "#define ") != 0) {
+ llvm::StringRef &Extra = ExtraPredefines[I];
+ if (!Extra.startswith("#define ")) {
Reader.Diag(diag::warn_pch_compiler_options_mismatch);
return true;
}
@@ -307,16 +277,13 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
= Extra.find_first_of("( \n\r", StartOfMacroName);
assert(EndOfMacroName != std::string::npos &&
"Couldn't find the end of the macro name");
- std::string MacroName = Extra.substr(StartOfMacroName,
- EndOfMacroName - StartOfMacroName);
+ llvm::StringRef MacroName = Extra.slice(StartOfMacroName, EndOfMacroName);
// Check whether this name was used somewhere in the PCH file. If
// so, defining it as a macro could change behavior, so we reject
// the PCH file.
- if (IdentifierInfo *II = Reader.get(MacroName.c_str(),
- MacroName.c_str() + MacroName.size())) {
- Reader.Diag(diag::warn_macro_name_used_in_pch)
- << II;
+ if (IdentifierInfo *II = Reader.get(MacroName)) {
+ Reader.Diag(diag::warn_macro_name_used_in_pch) << II;
return true;
}
@@ -650,11 +617,11 @@ bool PCHReader::Error(const char *Msg) {
///
/// \returns true if there was a mismatch (in which case the PCH file
/// should be ignored), or false otherwise.
-bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef,
- unsigned PCHPredefLen,
+bool PCHReader::CheckPredefinesBuffer(llvm::StringRef PCHPredef,
FileID PCHBufferID) {
if (Listener)
- return Listener->ReadPredefinesBuffer(PCHPredef, PCHPredefLen, PCHBufferID,
+ return Listener->ReadPredefinesBuffer(PCHPredef, PCHBufferID,
+ ActualOriginalFileName,
SuggestedPredefines);
return false;
}
@@ -1364,7 +1331,8 @@ PCHReader::ReadPCHBlock() {
break;
case pch::ORIGINAL_FILE_NAME:
- OriginalFileName.assign(BlobStart, BlobLen);
+ ActualOriginalFileName.assign(BlobStart, BlobLen);
+ OriginalFileName = ActualOriginalFileName;
MaybeAddSystemRootToFilename(OriginalFileName);
break;
@@ -1403,10 +1371,7 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
//
// FIXME: This shouldn't be here, we should just take a raw_ostream.
std::string ErrStr;
- if (FileName == "-")
- Buffer.reset(llvm::MemoryBuffer::getSTDIN());
- else
- Buffer.reset(llvm::MemoryBuffer::getFile(FileName.c_str(), &ErrStr));
+ Buffer.reset(llvm::MemoryBuffer::getFileOrSTDIN(FileName, &ErrStr));
if (!Buffer) {
Error(ErrStr.c_str());
return IgnorePCH;
@@ -1478,7 +1443,7 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
}
// Check the predefines buffer.
- if (CheckPredefinesBuffer(PCHPredefines, PCHPredefinesLen,
+ if (CheckPredefinesBuffer(llvm::StringRef(PCHPredefines, PCHPredefinesLen),
PCHPredefinesBufferID))
return IgnorePCH;
@@ -1741,6 +1706,7 @@ bool PCHReader::ParseLanguageOptions(
PARSE_LANGOPT(NoInline);
PARSE_LANGOPT(AccessControl);
PARSE_LANGOPT(CharIsSigned);
+ PARSE_LANGOPT(ShortWChar);
LangOpts.setGCMode((LangOptions::GCMode)Record[Idx]);
++Idx;
LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx]);
@@ -2213,6 +2179,14 @@ PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
return ReadDeclExpr();
case TemplateArgument::Type:
return GetDeclaratorInfo(Record, Index);
+ case TemplateArgument::Template: {
+ SourceLocation
+ QualStart = SourceLocation::getFromRawEncoding(Record[Index++]),
+ QualEnd = SourceLocation::getFromRawEncoding(Record[Index++]),
+ TemplateNameLoc = SourceLocation::getFromRawEncoding(Record[Index++]);
+ return TemplateArgumentLocInfo(SourceRange(QualStart, QualEnd),
+ TemplateNameLoc);
+ }
case TemplateArgument::Null:
case TemplateArgument::Integral:
case TemplateArgument::Declaration: