summaryrefslogtreecommitdiffstats
path: root/lib/Frontend
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Frontend')
-rw-r--r--lib/Frontend/ASTConsumers.cpp8
-rw-r--r--lib/Frontend/ASTUnit.cpp159
-rw-r--r--lib/Frontend/CMakeLists.txt4
-rw-r--r--lib/Frontend/DeclXML.cpp161
-rw-r--r--lib/Frontend/DocumentXML.cpp348
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp6
-rw-r--r--lib/Frontend/InitPreprocessor.cpp6
-rw-r--r--lib/Frontend/PCHReader.cpp814
-rw-r--r--lib/Frontend/PCHReaderDecl.cpp4
-rw-r--r--lib/Frontend/PCHReaderStmt.cpp1
-rw-r--r--lib/Frontend/PCHWriter.cpp10
-rw-r--r--lib/Frontend/PCHWriterDecl.cpp6
-rw-r--r--lib/Frontend/PCHWriterStmt.cpp1
-rw-r--r--lib/Frontend/PrintPreprocessedOutput.cpp35
-rw-r--r--lib/Frontend/RewriteBlocks.cpp2
-rw-r--r--lib/Frontend/RewriteObjC.cpp2
-rw-r--r--lib/Frontend/StmtXML.cpp100
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp13
-rw-r--r--lib/Frontend/TypeXML.cpp127
19 files changed, 1142 insertions, 665 deletions
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp
index 11c9251..5844be8 100644
--- a/lib/Frontend/ASTConsumers.cpp
+++ b/lib/Frontend/ASTConsumers.cpp
@@ -243,7 +243,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
}
case Decl::CXXMethod: {
const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
- if (D->isOutOfLineDefinition())
+ if (D->isOutOfLine())
Out << "[c++ method] ";
else if (D->isImplicit())
Out << "(c++ method) ";
@@ -273,7 +273,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
}
case Decl::CXXConstructor: {
const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
- if (D->isOutOfLineDefinition())
+ if (D->isOutOfLine())
Out << "[c++ ctor] ";
else if (D->isImplicit())
Out << "(c++ ctor) ";
@@ -302,7 +302,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
}
case Decl::CXXDestructor: {
const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
- if (D->isOutOfLineDefinition())
+ if (D->isOutOfLine())
Out << "[c++ dtor] ";
else if (D->isImplicit())
Out << "(c++ dtor) ";
@@ -318,7 +318,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
}
case Decl::CXXConversion: {
const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
- if (D->isOutOfLineDefinition())
+ if (D->isOutOfLine())
Out << "[c++ conversion] ";
else if (D->isImplicit())
Out << "(c++ conversion) ";
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
new file mode 100644
index 0000000..a7fbcda
--- /dev/null
+++ b/lib/Frontend/ASTUnit.cpp
@@ -0,0 +1,159 @@
+//===--- ASTUnit.cpp - ASTUnit utility ------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// ASTUnit Implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/PCHReader.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/Support/Compiler.h"
+
+using namespace clang;
+
+ASTUnit::ASTUnit() { }
+ASTUnit::~ASTUnit() { }
+
+namespace {
+
+/// \brief Gathers information from PCHReader that will be used to initialize
+/// a Preprocessor.
+class VISIBILITY_HIDDEN PCHInfoCollector : public PCHReaderListener {
+ LangOptions &LangOpt;
+ HeaderSearch &HSI;
+ std::string &TargetTriple;
+ std::string &Predefines;
+ unsigned &Counter;
+
+ unsigned NumHeaderInfos;
+
+public:
+ PCHInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI,
+ std::string &TargetTriple, std::string &Predefines,
+ unsigned &Counter)
+ : LangOpt(LangOpt), HSI(HSI), TargetTriple(TargetTriple),
+ Predefines(Predefines), Counter(Counter), NumHeaderInfos(0) {}
+
+ virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
+ LangOpt = LangOpts;
+ return false;
+ }
+
+ virtual bool ReadTargetTriple(const std::string &Triple) {
+ TargetTriple = Triple;
+ return false;
+ }
+
+ virtual bool ReadPredefinesBuffer(const char *PCHPredef,
+ unsigned PCHPredefLen,
+ FileID PCHBufferID,
+ std::string &SuggestedPredefines) {
+ Predefines = PCHPredef;
+ return false;
+ }
+
+ virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI) {
+ HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
+ }
+
+ virtual void ReadCounter(unsigned Value) {
+ Counter = Value;
+ }
+};
+
+} // anonymous namespace
+
+
+ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
+ FileManager &FileMgr,
+ std::string *ErrMsg) {
+
+ llvm::OwningPtr<ASTUnit> AST(new ASTUnit());
+
+ AST->DiagClient.reset(new TextDiagnosticBuffer());
+ AST->Diags.reset(new Diagnostic(AST->DiagClient.get()));
+
+ AST->HeaderInfo.reset(new HeaderSearch(FileMgr));
+ AST->SourceMgr.reset(new SourceManager());
+
+ Diagnostic &Diags = *AST->Diags.get();
+ SourceManager &SourceMgr = *AST->SourceMgr.get();
+
+ // Gather Info for preprocessor construction later on.
+
+ LangOptions LangInfo;
+ HeaderSearch &HeaderInfo = *AST->HeaderInfo.get();
+ std::string TargetTriple;
+ std::string Predefines;
+ unsigned Counter;
+
+ llvm::OwningPtr<PCHReader> Reader;
+ llvm::OwningPtr<ExternalASTSource> Source;
+
+ Reader.reset(new PCHReader(SourceMgr, FileMgr, Diags));
+ Reader->setListener(new PCHInfoCollector(LangInfo, HeaderInfo, TargetTriple,
+ Predefines, Counter));
+
+ switch (Reader->ReadPCH(Filename)) {
+ case PCHReader::Success:
+ break;
+
+ case PCHReader::Failure:
+ // Unrecoverable failure: don't even try to process the input
+ // file.
+ if (ErrMsg)
+ *ErrMsg = "Could not load PCH file";
+ return NULL;
+
+ case PCHReader::IgnorePCH:
+ assert(0 && "Is there a validation that should not have happened ?");
+ }
+
+ // PCH loaded successfully. Now create the preprocessor.
+
+ // Get information about the target being compiled for.
+ AST->Target.reset(TargetInfo::CreateTargetInfo(TargetTriple));
+ AST->PP.reset(new Preprocessor(Diags, LangInfo, *AST->Target.get(),
+ SourceMgr, HeaderInfo));
+ Preprocessor &PP = *AST->PP.get();
+
+ PP.setPredefines(Predefines);
+ PP.setCounterValue(Counter);
+ Reader->setPreprocessor(PP);
+
+ // Create and initialize the ASTContext.
+
+ AST->Ctx.reset(new ASTContext(LangInfo,
+ SourceMgr,
+ *AST->Target.get(),
+ PP.getIdentifierTable(),
+ PP.getSelectorTable(),
+ PP.getBuiltinInfo(),
+ /* FreeMemory = */ true,
+ /* size_reserve = */0));
+ ASTContext &Context = *AST->Ctx.get();
+
+ Reader->InitializeContext(Context);
+
+ // Attach the PCH reader to the AST context as an external AST
+ // source, so that declarations will be deserialized from the
+ // PCH file as needed.
+ Source.reset(Reader.take());
+ Context.setExternalSource(Source);
+
+ return AST.take();
+}
diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt
index 649f9da..330b4db 100644
--- a/lib/Frontend/CMakeLists.txt
+++ b/lib/Frontend/CMakeLists.txt
@@ -5,6 +5,7 @@ add_clang_library(clangFrontend
ASTConsumers.cpp
Backend.cpp
CacheTokens.cpp
+ DeclXML.cpp
DependencyFile.cpp
DiagChecker.cpp
DocumentXML.cpp
@@ -31,5 +32,8 @@ add_clang_library(clangFrontend
StmtXML.cpp
TextDiagnosticBuffer.cpp
TextDiagnosticPrinter.cpp
+ TypeXML.cpp
Warnings.cpp
)
+
+add_dependencies(clangSema ClangDiagnosticFrontend)
diff --git a/lib/Frontend/DeclXML.cpp b/lib/Frontend/DeclXML.cpp
new file mode 100644
index 0000000..5c21999
--- /dev/null
+++ b/lib/Frontend/DeclXML.cpp
@@ -0,0 +1,161 @@
+//===--- DeclXML.cpp - XML implementation for Decl ASTs -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the XML document class, which provides the means to
+// dump out the AST in a XML form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/DocumentXML.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/Expr.h"
+
+namespace clang {
+
+//---------------------------------------------------------
+class DocumentXML::DeclPrinter : public DeclVisitor<DocumentXML::DeclPrinter>
+{
+ DocumentXML& Doc;
+
+ void addSubNodes(FunctionDecl* FD)
+ {
+ for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i)
+ {
+ Visit(FD->getParamDecl(i));
+ Doc.toParent();
+ }
+ }
+
+ void addSubNodes(RecordDecl* RD)
+ {
+ for (RecordDecl::field_iterator i = RD->field_begin(*Doc.Ctx), e = RD->field_end(*Doc.Ctx); i != e; ++i)
+ {
+ Visit(*i);
+ Doc.toParent();
+ }
+ }
+
+ void addSubNodes(EnumDecl* ED)
+ {
+ for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(*Doc.Ctx), e = ED->enumerator_end(*Doc.Ctx); i != e; ++i)
+ {
+ Visit(*i);
+ Doc.toParent();
+ }
+ }
+
+ void addSubNodes(EnumConstantDecl* ECD)
+ {
+ if (ECD->getInitExpr())
+ {
+ Doc.PrintStmt(ECD->getInitExpr());
+ }
+ }
+
+ void addSubNodes(FieldDecl* FdD)
+ {
+ if (FdD->isBitField())
+ {
+ Doc.PrintStmt(FdD->getBitWidth());
+ }
+ }
+
+ void addSubNodes(VarDecl* V)
+ {
+ if (V->getInit())
+ {
+ Doc.PrintStmt(V->getInit());
+ }
+ }
+
+ void addSubNodes(ParmVarDecl* argDecl)
+ {
+ if (argDecl->getDefaultArg())
+ {
+ Doc.PrintStmt(argDecl->getDefaultArg());
+ }
+ }
+
+ void addSpecialAttribute(const char* pName, EnumDecl* ED)
+ {
+ const QualType& enumType = ED->getIntegerType();
+ if (!enumType.isNull())
+ {
+ Doc.addAttribute(pName, enumType);
+ }
+ }
+
+ void addIdAttribute(LinkageSpecDecl* ED)
+ {
+ Doc.addAttribute("id", ED);
+ }
+
+ void addIdAttribute(NamedDecl* ND)
+ {
+ Doc.addAttribute("id", ND);
+ }
+
+public:
+ DeclPrinter(DocumentXML& doc) : Doc(doc) {}
+
+#define NODE_XML( CLASS, NAME ) \
+ void Visit##CLASS(CLASS* T) \
+ { \
+ Doc.addSubNode(NAME);
+
+#define ID_ATTRIBUTE_XML addIdAttribute(T);
+#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN);
+#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN);
+#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocation(T->getLocation());
+#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, T);
+
+#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = false; \
+ switch (T->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = true; \
+ switch (T->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
+#define END_ENUM_XML } }
+#define END_NODE_XML }
+
+#define SUB_NODE_XML( CLASS ) addSubNodes(T);
+#define SUB_NODE_SEQUENCE_XML( CLASS ) addSubNodes(T);
+#define SUB_NODE_OPT_XML( CLASS ) addSubNodes(T);
+
+#include "clang/Frontend/DeclXML.def"
+};
+
+
+//---------------------------------------------------------
+void DocumentXML::writeDeclToXML(Decl *D)
+{
+ DeclPrinter(*this).Visit(D);
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ {
+ if (Stmt *Body = FD->getBody(*Ctx)) {
+ addSubNode("Body");
+ PrintStmt(Body);
+ toParent();
+ }
+ }
+ toParent();
+}
+
+//---------------------------------------------------------
+} // NS clang
+
diff --git a/lib/Frontend/DocumentXML.cpp b/lib/Frontend/DocumentXML.cpp
index 7562d2a..19a7573 100644
--- a/lib/Frontend/DocumentXML.cpp
+++ b/lib/Frontend/DocumentXML.cpp
@@ -14,92 +14,66 @@
#include "clang/Frontend/DocumentXML.h"
#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/Expr.h"
+#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/StringExtras.h"
namespace clang {
//---------------------------------------------------------
-struct DocumentXML::NodeXML
-{
- std::string Name;
- NodeXML* Parent;
-
- NodeXML(const std::string& name, NodeXML* parent) :
- Name(name),
- Parent(parent)
- {}
-};
-
-//---------------------------------------------------------
DocumentXML::DocumentXML(const std::string& rootName, llvm::raw_ostream& out) :
- Root(new NodeXML(rootName, 0)),
- CurrentNode(Root),
Out(out),
Ctx(0),
- CurrentIndent(0),
HasCurrentNodeSubNodes(false)
{
+ NodeStack.push(rootName);
Out << "<?xml version=\"1.0\"?>\n<" << rootName;
}
//---------------------------------------------------------
-DocumentXML::~DocumentXML()
-{
- assert(CurrentNode == Root && "not completely backtracked");
- delete Root;
-}
-
-//---------------------------------------------------------
DocumentXML& DocumentXML::addSubNode(const std::string& name)
{
if (!HasCurrentNodeSubNodes)
{
Out << ">\n";
}
- CurrentNode = new NodeXML(name, CurrentNode);
+ NodeStack.push(name);
HasCurrentNodeSubNodes = false;
- CurrentIndent += 2;
Indent();
- Out << "<" << CurrentNode->Name;
+ Out << "<" << NodeStack.top();
return *this;
}
//---------------------------------------------------------
void DocumentXML::Indent()
{
- for (int i = 0; i < CurrentIndent; ++i)
+ for (size_t i = 0, e = (NodeStack.size() - 1) * 2; i < e; ++i)
Out << ' ';
}
//---------------------------------------------------------
DocumentXML& DocumentXML::toParent()
{
- assert(CurrentNode != Root && "to much backtracking");
+ assert(NodeStack.size() > 1 && "to much backtracking");
if (HasCurrentNodeSubNodes)
{
Indent();
- Out << "</" << CurrentNode->Name << ">\n";
+ Out << "</" << NodeStack.top() << ">\n";
}
else
{
Out << "/>\n";
}
- NodeXML* NodeToDelete = CurrentNode;
- CurrentNode = CurrentNode->Parent;
- delete NodeToDelete;
+ NodeStack.pop();
HasCurrentNodeSubNodes = true;
- CurrentIndent -= 2;
return *this;
}
//---------------------------------------------------------
namespace {
-enum tIdType { ID_NORMAL, ID_FILE, ID_LAST };
+enum tIdType { ID_NORMAL, ID_FILE, ID_LABEL, ID_LAST };
unsigned getNewId(tIdType idType)
{
@@ -110,7 +84,7 @@ unsigned getNewId(tIdType idType)
//---------------------------------------------------------
inline std::string getPrefixedId(unsigned uId, tIdType idType)
{
- static const char idPrefix[ID_LAST] = { '_', 'f' };
+ static const char idPrefix[ID_LAST] = { '_', 'f', 'l' };
char buffer[20];
char* BufPtr = llvm::utohex_buffer(uId, buffer + 20);
*--BufPtr = idPrefix[idType];
@@ -132,6 +106,7 @@ bool addToMap(T& idMap, const V& value, tIdType idType = ID_NORMAL)
} // anon NS
+
//---------------------------------------------------------
std::string DocumentXML::escapeString(const char* pStr, std::string::size_type len)
{
@@ -170,7 +145,7 @@ std::string DocumentXML::escapeString(const char* pStr, std::string::size_type l
//---------------------------------------------------------
void DocumentXML::finalize()
{
- assert(CurrentNode == Root && "not completely backtracked");
+ assert(NodeStack.size() == 1 && "not completely backtracked");
addSubNode("ReferenceSection");
addSubNode("Types");
@@ -179,71 +154,15 @@ void DocumentXML::finalize()
{
if (i->first.getCVRQualifiers() != 0)
{
- addSubNode("CvQualifiedType");
+ writeTypeToXML(i->first);
addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
- addAttribute("type", getPrefixedId(BasicTypes[i->first.getTypePtr()], ID_NORMAL));
- if (i->first.isConstQualified()) addAttribute("const", "1");
- if (i->first.isVolatileQualified()) addAttribute("volatile", "1");
- if (i->first.isRestrictQualified()) addAttribute("restrict", "1");
toParent();
}
}
for (XML::IdMap<const Type*>::iterator i = BasicTypes.begin(), e = BasicTypes.end(); i != e; ++i)
{
- // don't use the get methods as they strip of typedef infos
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(i->first)) {
- addSubNode("FundamentalType");
- addAttribute("name", BT->getName(Ctx->getLangOptions().CPlusPlus));
- }
- else if (const PointerType *PT = dyn_cast<PointerType>(i->first)) {
- addSubNode("PointerType");
- addTypeAttribute(PT->getPointeeType());
- }
- else if (dyn_cast<FunctionType>(i->first) != 0) {
- addSubNode("FunctionType");
- }
- else if (const ReferenceType *RT = dyn_cast<ReferenceType>(i->first)) {
- addSubNode("ReferenceType");
- addTypeAttribute(RT->getPointeeType());
- }
- else if (const TypedefType * TT = dyn_cast<TypedefType>(i->first)) {
- addSubNode("Typedef");
- addAttribute("name", TT->getDecl()->getNameAsString());
- addTypeAttribute(TT->getDecl()->getUnderlyingType());
- addContextAttribute(TT->getDecl()->getDeclContext());
- }
- else if (const QualifiedNameType *QT = dyn_cast<QualifiedNameType>(i->first)) {
- addSubNode("QualifiedNameType");
- addTypeAttribute(QT->getNamedType());
- }
- else if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(i->first)) {
- addSubNode("ArrayType");
- addAttribute("min", 0);
- addAttribute("max", (CAT->getSize() - 1).toString(10, false));
- addTypeAttribute(CAT->getElementType());
- }
- else if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(i->first)) {
- addSubNode("VariableArrayType");
- addTypeAttribute(VAT->getElementType());
- }
- else if (const TagType *RET = dyn_cast<TagType>(i->first)) {
- const TagDecl *tagDecl = RET->getDecl();
- std::string tagKind = tagDecl->getKindName();
- tagKind[0] = std::toupper(tagKind[0]);
- addSubNode(tagKind);
- addAttribute("name", tagDecl->getNameAsString());
- addContextAttribute(tagDecl->getDeclContext());
- }
- else if (const VectorType* VT = dyn_cast<VectorType>(i->first)) {
- addSubNode("VectorType");
- addTypeAttribute(VT->getElementType());
- addAttribute("num_elements", VT->getNumElements());
- }
- else
- {
- addSubNode("FIXMEType");
- }
+ writeTypeToXML(i->first);
addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
toParent();
}
@@ -267,7 +186,7 @@ void DocumentXML::finalize()
if (const DeclContext* parent = i->first->getParent())
{
- addContextAttribute(parent);
+ addAttribute("context", parent);
}
toParent();
}
@@ -285,21 +204,21 @@ void DocumentXML::finalize()
toParent().toParent();
// write the root closing node (which has always subnodes)
- Out << "</" << CurrentNode->Name << ">\n";
+ Out << "</" << NodeStack.top() << ">\n";
}
//---------------------------------------------------------
-void DocumentXML::addTypeAttribute(const QualType& pType)
+void DocumentXML::addAttribute(const char* pAttributeName, const QualType& pType)
{
addTypeRecursively(pType);
- addAttribute("type", getPrefixedId(Types[pType], ID_NORMAL));
+ addAttribute(pAttributeName, getPrefixedId(Types[pType], ID_NORMAL));
}
//---------------------------------------------------------
-void DocumentXML::addTypeIdAttribute(const Type* pType)
+void DocumentXML::addPtrAttribute(const char* pAttributeName, const Type* pType)
{
- addBasicTypeRecursively(pType);
- addAttribute("id", getPrefixedId(BasicTypes[pType], ID_NORMAL));
+ addTypeRecursively(pType);
+ addAttribute(pAttributeName, getPrefixedId(BasicTypes[pType], ID_NORMAL));
}
//---------------------------------------------------------
@@ -307,7 +226,7 @@ void DocumentXML::addTypeRecursively(const QualType& pType)
{
if (addToMap(Types, pType))
{
- addBasicTypeRecursively(pType.getTypePtr());
+ addTypeRecursively(pType.getTypePtr());
// beautifier: a non-qualified type shall be transparent
if (pType.getCVRQualifiers() == 0)
{
@@ -317,43 +236,49 @@ void DocumentXML::addTypeRecursively(const QualType& pType)
}
//---------------------------------------------------------
-void DocumentXML::addBasicTypeRecursively(const Type* pType)
+void DocumentXML::addTypeRecursively(const Type* pType)
{
if (addToMap(BasicTypes, pType))
{
- if (const PointerType *PT = dyn_cast<PointerType>(pType)) {
- addTypeRecursively(PT->getPointeeType());
- }
- else if (const ReferenceType *RT = dyn_cast<ReferenceType>(pType)) {
- addTypeRecursively(RT->getPointeeType());
- }
- else if (const TypedefType *TT = dyn_cast<TypedefType>(pType)) {
- addTypeRecursively(TT->getDecl()->getUnderlyingType());
- addContextsRecursively(TT->getDecl()->getDeclContext());
- }
- else if (const QualifiedNameType *QT = dyn_cast<QualifiedNameType>(pType)) {
- addTypeRecursively(QT->getNamedType());
- // FIXME: what to do with NestedNameSpecifier or shall this type be transparent?
- }
- else if (const ArrayType *AT = dyn_cast<ArrayType>(pType)) {
- addTypeRecursively(AT->getElementType());
- // FIXME: doesn't work in the immediate streaming approach
- /*if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(AT))
- {
- addSubNode("VariableArraySizeExpression");
- PrintStmt(VAT->getSizeExpr());
- toParent();
- }*/
+ addParentTypes(pType);
+/*
+ // FIXME: doesn't work in the immediate streaming approach
+ if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(pType))
+ {
+ addSubNode("VariableArraySizeExpression");
+ PrintStmt(VAT->getSizeExpr());
+ toParent();
}
+*/
}
}
//---------------------------------------------------------
-void DocumentXML::addContextAttribute(const DeclContext *DC, tContextUsage usage)
+void DocumentXML::addPtrAttribute(const char* pName, const DeclContext* DC)
{
addContextsRecursively(DC);
- const char* pAttributeTags[2] = { "context", "id" };
- addAttribute(pAttributeTags[usage], getPrefixedId(Contexts[DC], ID_NORMAL));
+ addAttribute(pName, getPrefixedId(Contexts[DC], ID_NORMAL));
+}
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pAttributeName, const NamedDecl* D)
+{
+ if (const DeclContext* DC = dyn_cast<DeclContext>(D))
+ {
+ addContextsRecursively(DC);
+ addAttribute(pAttributeName, getPrefixedId(Contexts[DC], ID_NORMAL));
+ }
+ else
+ {
+ addToMap(Decls, D);
+ addAttribute(pAttributeName, getPrefixedId(Decls[D], ID_NORMAL));
+ }
+}
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pName, const NamespaceDecl* D)
+{
+ addPtrAttribute(pName, static_cast<const DeclContext*>(D));
}
//---------------------------------------------------------
@@ -372,6 +297,15 @@ void DocumentXML::addSourceFileAttribute(const std::string& fileName)
addAttribute("file", getPrefixedId(SourceFiles[fileName], ID_FILE));
}
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pName, const LabelStmt* L)
+{
+ addToMap(Labels, L, ID_LABEL);
+ addAttribute(pName, getPrefixedId(Labels[L], ID_LABEL));
+}
+
+
//---------------------------------------------------------
PresumedLoc DocumentXML::addLocation(const SourceLocation& Loc)
{
@@ -417,161 +351,9 @@ void DocumentXML::addLocationRange(const SourceRange& R)
}
//---------------------------------------------------------
-void DocumentXML::PrintFunctionDecl(FunctionDecl *FD)
-{
- switch (FD->getStorageClass()) {
- default: assert(0 && "Unknown storage class");
- case FunctionDecl::None: break;
- case FunctionDecl::Extern: addAttribute("storage_class", "extern"); break;
- case FunctionDecl::Static: addAttribute("storage_class", "static"); break;
- case FunctionDecl::PrivateExtern: addAttribute("storage_class", "__private_extern__"); break;
- }
-
- if (FD->isInline())
- addAttribute("inline", "1");
-
- const FunctionType *AFT = FD->getType()->getAsFunctionType();
- addTypeAttribute(AFT->getResultType());
- addBasicTypeRecursively(AFT);
-
- if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(AFT)) {
- addAttribute("num_args", FD->getNumParams());
- for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
- addSubNode("Argument");
- ParmVarDecl *argDecl = FD->getParamDecl(i);
- addAttribute("name", argDecl->getNameAsString());
- addTypeAttribute(FT->getArgType(i));
- addDeclIdAttribute(argDecl);
- if (argDecl->getDefaultArg())
- {
- addAttribute("default_arg", "1");
- PrintStmt(argDecl->getDefaultArg());
- }
- toParent();
- }
-
- if (FT->isVariadic()) {
- addSubNode("Ellipsis").toParent();
- }
- } else {
- assert(isa<FunctionNoProtoType>(AFT));
- }
-}
-
-//---------------------------------------------------------
-void DocumentXML::addRefAttribute(const NamedDecl* D)
-{
- // FIXME: in case of CXX inline member functions referring to a member defined
- // after the function it needs to be tested, if the ids are already there
- // (should work, but I couldn't test it)
- if (const DeclContext* DC = dyn_cast<DeclContext>(D))
- {
- addAttribute("ref", getPrefixedId(Contexts[DC], ID_NORMAL));
- }
- else
- {
- addAttribute("ref", getPrefixedId(Decls[D], ID_NORMAL));
- }
-}
-
-//---------------------------------------------------------
-void DocumentXML::addDeclIdAttribute(const NamedDecl* D)
-{
- addToMap(Decls, D);
- addAttribute("id", getPrefixedId(Decls[D], ID_NORMAL));
-}
-
-//---------------------------------------------------------
void DocumentXML::PrintDecl(Decl *D)
{
- addSubNode(D->getDeclKindName());
- addContextAttribute(D->getDeclContext());
- addLocation(D->getLocation());
- if (DeclContext* DC = dyn_cast<DeclContext>(D))
- {
- addContextAttribute(DC, CONTEXT_AS_ID);
- }
-
- if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
- addAttribute("name", ND->getNameAsString());
-
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- PrintFunctionDecl(FD);
- if (Stmt *Body = FD->getBody(*Ctx)) {
- addSubNode("Body");
- PrintStmt(Body);
- toParent();
- }
- } else if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
- addBasicTypeRecursively(RD->getTypeForDecl());
- addAttribute("type", getPrefixedId(BasicTypes[RD->getTypeForDecl()], ID_NORMAL));
- if (!RD->isDefinition())
- {
- addAttribute("forward", "1");
- }
-
- for (RecordDecl::field_iterator i = RD->field_begin(*Ctx), e = RD->field_end(*Ctx); i != e; ++i)
- {
- PrintDecl(*i);
- }
- } else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
- const QualType& enumType = ED->getIntegerType();
- if (!enumType.isNull())
- {
- addTypeAttribute(enumType);
- for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(*Ctx), e = ED->enumerator_end(*Ctx); i != e; ++i)
- {
- PrintDecl(*i);
- }
- }
- } else if (EnumConstantDecl* ECD = dyn_cast<EnumConstantDecl>(D)) {
- addTypeAttribute(ECD->getType());
- addAttribute("value", ECD->getInitVal().toString(10, true));
- if (ECD->getInitExpr())
- {
- PrintStmt(ECD->getInitExpr());
- }
- } else if (FieldDecl *FdD = dyn_cast<FieldDecl>(D)) {
- addTypeAttribute(FdD->getType());
- addDeclIdAttribute(ND);
- if (FdD->isMutable())
- addAttribute("mutable", "1");
- if (FdD->isBitField())
- {
- addAttribute("bitfield", "1");
- PrintStmt(FdD->getBitWidth());
- }
- } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
- addTypeIdAttribute(Ctx->getTypedefType(TD).getTypePtr());
- addTypeAttribute(TD->getUnderlyingType());
- } else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
- addTypeAttribute(VD->getType());
- addDeclIdAttribute(ND);
-
- VarDecl *V = dyn_cast<VarDecl>(VD);
- if (V && V->getStorageClass() != VarDecl::None)
- {
- addAttribute("storage_class", VarDecl::getStorageClassSpecifierString(V->getStorageClass()));
- }
-
- if (V && V->getInit())
- {
- PrintStmt(V->getInit());
- }
- }
- } else if (LinkageSpecDecl* LSD = dyn_cast<LinkageSpecDecl>(D)) {
- switch (LSD->getLanguage())
- {
- case LinkageSpecDecl::lang_c: addAttribute("lang", "C"); break;
- case LinkageSpecDecl::lang_cxx: addAttribute("lang", "CXX"); break;
- default: assert(0 && "Unexpected lang id");
- }
- } else if (isa<FileScopeAsmDecl>(D)) {
- // FIXME: Implement this
- } else {
- assert(0 && "Unexpected decl");
- }
- toParent();
+ writeDeclToXML(D);
}
//---------------------------------------------------------
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index 6383c20..7a2b3a7 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -138,6 +138,12 @@ void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang) {
false);
AddPath("/usr/include/c++/4.1.3/backward", System, true, false, false);
+ // Ubuntu 9.04
+ AddPath("/usr/include/c++/4.3.3", System, true, false, false);
+ AddPath("/usr/include/c++/4.3.3/x86_64-linux-gnu/", System, true, false,
+ false);
+ AddPath("/usr/include/c++/4.3.3/backward", System, true, false, false);
+
// Fedora 8
AddPath("/usr/include/c++/4.1.2", System, true, false, false);
AddPath("/usr/include/c++/4.1.2/i386-redhat-linux", System, true, false,
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index 6cff75d..41908ad 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -472,11 +472,7 @@ bool InitializePreprocessor(Preprocessor &PP,
AddImplicitIncludePTH(PredefineBuffer, PP, I->first);
else
AddImplicitInclude(PredefineBuffer, I->first);
- }
-
- LineDirective = "# 2 \"<built-in>\" 2 3\n";
- PredefineBuffer.insert(PredefineBuffer.end(),
- LineDirective, LineDirective+strlen(LineDirective));
+ }
// Null terminate PredefinedBuffer and add it.
PredefineBuffer.push_back(0);
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 87fc839..96f21f1 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -36,11 +36,321 @@
using namespace clang;
//===----------------------------------------------------------------------===//
+// PCH reader validator implementation
+//===----------------------------------------------------------------------===//
+
+PCHReaderListener::~PCHReaderListener() {}
+
+bool
+PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) {
+ const LangOptions &PPLangOpts = PP.getLangOptions();
+#define PARSE_LANGOPT_BENIGN(Option)
+#define PARSE_LANGOPT_IMPORTANT(Option, DiagID) \
+ if (PPLangOpts.Option != LangOpts.Option) { \
+ Reader.Diag(DiagID) << LangOpts.Option << PPLangOpts.Option; \
+ return true; \
+ }
+
+ PARSE_LANGOPT_BENIGN(Trigraphs);
+ PARSE_LANGOPT_BENIGN(BCPLComment);
+ PARSE_LANGOPT_BENIGN(DollarIdents);
+ PARSE_LANGOPT_BENIGN(AsmPreprocessor);
+ PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions);
+ PARSE_LANGOPT_BENIGN(ImplicitInt);
+ PARSE_LANGOPT_BENIGN(Digraphs);
+ PARSE_LANGOPT_BENIGN(HexFloats);
+ PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99);
+ PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions);
+ PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus);
+ PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x);
+ PARSE_LANGOPT_BENIGN(CXXOperatorName);
+ PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c);
+ PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2);
+ PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi);
+ PARSE_LANGOPT_BENIGN(PascalStrings);
+ PARSE_LANGOPT_BENIGN(WritableStrings);
+ PARSE_LANGOPT_IMPORTANT(LaxVectorConversions,
+ diag::warn_pch_lax_vector_conversions);
+ PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
+ PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
+ PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
+ PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins);
+ PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics,
+ diag::warn_pch_thread_safe_statics);
+ PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
+ PARSE_LANGOPT_BENIGN(EmitAllDecls);
+ PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
+ PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking);
+ PARSE_LANGOPT_IMPORTANT(HeinousExtensions,
+ diag::warn_pch_heinous_extensions);
+ // FIXME: Most of the options below are benign if the macro wasn't
+ // used. Unfortunately, this means that a PCH compiled without
+ // optimization can't be used with optimization turned on, even
+ // though the only thing that changes is whether __OPTIMIZE__ was
+ // defined... but if __OPTIMIZE__ never showed up in the header, it
+ // doesn't matter. We could consider making this some special kind
+ // of check.
+ PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize);
+ PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size);
+ PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static);
+ PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level);
+ PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline);
+ 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);
+ if ((PPLangOpts.getGCMode() != 0) != (LangOpts.getGCMode() != 0)) {
+ Reader.Diag(diag::warn_pch_gc_mode)
+ << LangOpts.getGCMode() << PPLangOpts.getGCMode();
+ return true;
+ }
+ PARSE_LANGOPT_BENIGN(getVisibilityMode());
+ PARSE_LANGOPT_BENIGN(InstantiationDepth);
+#undef PARSE_LANGOPT_IRRELEVANT
+#undef PARSE_LANGOPT_BENIGN
+
+ return false;
+}
+
+bool PCHValidator::ReadTargetTriple(const std::string &Triple) {
+ if (Triple != PP.getTargetInfo().getTargetTriple()) {
+ Reader.Diag(diag::warn_pch_target_triple)
+ << Triple << PP.getTargetInfo().getTargetTriple();
+ 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;
+ }
+
+ 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,
+ FileID PCHBufferID,
+ 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)
+ 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);
+
+ // Sort both sets of predefined buffer lines, since
+ 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;
+ std::set_difference(PCHLines.begin(), PCHLines.end(),
+ CmdLineLines.begin(), CmdLineLines.end(),
+ std::back_inserter(MissingPredefines));
+
+ 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) {
+ Reader.Diag(diag::warn_pch_compiler_options_mismatch);
+ return true;
+ }
+
+ // 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);
+
+ // Determine whether this macro was given a different definition
+ // on the command line.
+ std::string MacroDefStart = "#define " + MacroName;
+ std::string::size_type MacroDefLen = MacroDefStart.size();
+ std::vector<std::string>::iterator ConflictPos
+ = std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(),
+ MacroDefStart);
+ for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) {
+ if (!startsWith(*ConflictPos, MacroDefStart)) {
+ // Different macro; we're done.
+ ConflictPos = CmdLineLines.end();
+ break;
+ }
+
+ assert(ConflictPos->size() > MacroDefLen &&
+ "Invalid #define in predefines buffer?");
+ if ((*ConflictPos)[MacroDefLen] != ' ' &&
+ (*ConflictPos)[MacroDefLen] != '(')
+ continue; // Longer macro name; keep trying.
+
+ // We found a conflicting macro definition.
+ break;
+ }
+
+ if (ConflictPos != CmdLineLines.end()) {
+ Reader.Diag(diag::warn_cmdline_conflicting_macro_def)
+ << 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;
+
+ 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 (ConflictingDefines)
+ continue; // Don't complain if there are already conflicting defs
+
+ if (!MissingDefines) {
+ Reader.Diag(diag::warn_cmdline_missing_macro_defs);
+ MissingDefines = true;
+ }
+
+ // 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_using_macro_def_from_pch);
+ }
+
+ if (ConflictingDefines)
+ return true;
+
+ // Determine what predefines were introduced based on command-line
+ // 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::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) {
+ Reader.Diag(diag::warn_pch_compiler_options_mismatch);
+ return true;
+ }
+
+ // This is an extra macro definition. Determine the name of the
+ // macro we're defining.
+ std::string::size_type StartOfMacroName = strlen("#define ");
+ std::string::size_type EndOfMacroName
+ = 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);
+
+ // 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;
+ return true;
+ }
+
+ // Add this definition to the suggested predefines buffer.
+ SuggestedPredefines += Extra;
+ SuggestedPredefines += '\n';
+ }
+
+ // If we get here, it's because the predefines buffer had compatible
+ // contents. Accept the PCH file.
+ return false;
+}
+
+void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI) {
+ PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
+}
+
+void PCHValidator::ReadCounter(unsigned Value) {
+ PP.setCounterValue(Value);
+}
+
+
+
+//===----------------------------------------------------------------------===//
// PCH reader implementation
//===----------------------------------------------------------------------===//
PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context)
- : SemaObj(0), PP(PP), Context(Context), Consumer(0),
+ : Listener(new PCHValidator(PP, *this)), SourceMgr(PP.getSourceManager()),
+ FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()),
+ SemaObj(0), PP(&PP), Context(Context), Consumer(0),
+ IdentifierTableData(0), IdentifierLookupTable(0),
+ IdentifierOffsets(0),
+ MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
+ TotalSelectorsInMethodPool(0), SelectorOffsets(0),
+ TotalNumSelectors(0), NumStatHits(0), NumStatMisses(0),
+ NumSLocEntriesRead(0), NumStatementsRead(0),
+ NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
+ NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0) { }
+
+PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
+ Diagnostic &Diags)
+ : SourceMgr(SourceMgr), FileMgr(FileMgr), Diags(Diags),
+ SemaObj(0), PP(0), Context(0), Consumer(0),
IdentifierTableData(0), IdentifierLookupTable(0),
IdentifierOffsets(0),
MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
@@ -314,53 +624,11 @@ typedef OnDiskChainedHashTable<PCHIdentifierLookupTrait>
// FIXME: use the diagnostics machinery
bool PCHReader::Error(const char *Msg) {
- Diagnostic &Diags = PP.getDiagnostics();
unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Fatal, Msg);
Diag(DiagID);
return true;
}
-/// \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
-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;
- }
-
- 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());
-}
-
/// \brief Check the contents of the predefines buffer against the
/// contents of the predefines buffer used to build the PCH file.
///
@@ -381,158 +649,9 @@ static inline bool startsWith(const std::string &Haystack,
bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef,
unsigned PCHPredefLen,
FileID PCHBufferID) {
- 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)
- 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);
-
- // Sort both sets of predefined buffer lines, since
- 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;
- std::set_difference(PCHLines.begin(), PCHLines.end(),
- CmdLineLines.begin(), CmdLineLines.end(),
- std::back_inserter(MissingPredefines));
-
- 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) {
- Diag(diag::warn_pch_compiler_options_mismatch);
- return true;
- }
-
- // 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);
-
- // Determine whether this macro was given a different definition
- // on the command line.
- std::string MacroDefStart = "#define " + MacroName;
- std::string::size_type MacroDefLen = MacroDefStart.size();
- std::vector<std::string>::iterator ConflictPos
- = std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(),
- MacroDefStart);
- for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) {
- if (!startsWith(*ConflictPos, MacroDefStart)) {
- // Different macro; we're done.
- ConflictPos = CmdLineLines.end();
- break;
- }
-
- assert(ConflictPos->size() > MacroDefLen &&
- "Invalid #define in predefines buffer?");
- if ((*ConflictPos)[MacroDefLen] != ' ' &&
- (*ConflictPos)[MacroDefLen] != '(')
- continue; // Longer macro name; keep trying.
-
- // We found a conflicting macro definition.
- break;
- }
-
- if (ConflictPos != CmdLineLines.end()) {
- Diag(diag::warn_cmdline_conflicting_macro_def)
- << 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);
- 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 (ConflictingDefines)
- continue; // Don't complain if there are already conflicting defs
-
- if (!MissingDefines) {
- Diag(diag::warn_cmdline_missing_macro_defs);
- MissingDefines = true;
- }
-
- // 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);
- Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch);
- }
-
- if (ConflictingDefines)
- return true;
-
- // Determine what predefines were introduced based on command-line
- // 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::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) {
- Diag(diag::warn_pch_compiler_options_mismatch);
- return true;
- }
-
- // This is an extra macro definition. Determine the name of the
- // macro we're defining.
- std::string::size_type StartOfMacroName = strlen("#define ");
- std::string::size_type EndOfMacroName
- = 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);
-
- // 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 = get(MacroName.c_str(),
- MacroName.c_str() + MacroName.size())) {
- Diag(diag::warn_macro_name_used_in_pch)
- << II;
- return true;
- }
-
- // Add this definition to the suggested predefines buffer.
- SuggestedPredefines += Extra;
- SuggestedPredefines += '\n';
- }
-
- // If we get here, it's because the predefines buffer had compatible
- // contents. Accept the PCH file.
+ if (Listener)
+ return Listener->ReadPredefinesBuffer(PCHPredef, PCHPredefLen, PCHBufferID,
+ SuggestedPredefines);
return false;
}
@@ -714,9 +833,7 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
return Failure;
}
- SourceManager &SourceMgr = PP.getSourceManager();
RecordData Record;
- unsigned NumHeaderInfos = 0;
while (true) {
unsigned Code = SLocEntryCursor.ReadCode();
if (Code == llvm::bitc::END_BLOCK) {
@@ -761,7 +878,8 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
HFI.DirInfo = Record[1];
HFI.NumIncludes = Record[2];
HFI.ControllingMacroID = Record[3];
- PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
+ if (Listener)
+ Listener->ReadHeaderFileInfo(HFI);
break;
}
@@ -794,7 +912,6 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
return Failure;
}
- SourceManager &SourceMgr = PP.getSourceManager();
RecordData Record;
const char *BlobStart;
unsigned BlobLen;
@@ -804,9 +921,15 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
return Failure;
case pch::SM_SLOC_FILE_ENTRY: {
- const FileEntry *File
- = PP.getFileManager().getFile(BlobStart, BlobStart + BlobLen);
- // FIXME: Error recovery if file cannot be found.
+ const FileEntry *File = FileMgr.getFile(BlobStart, BlobStart + BlobLen);
+ if (File == 0) {
+ std::string ErrorStr = "could not find file '";
+ ErrorStr.append(BlobStart, BlobLen);
+ ErrorStr += "' referenced by PCH file";
+ Error(ErrorStr.c_str());
+ return Failure;
+ }
+
FileID FID = SourceMgr.createFileID(File,
SourceLocation::getFromRawEncoding(Record[1]),
(SrcMgr::CharacteristicKind)Record[2],
@@ -879,6 +1002,8 @@ bool PCHReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,
}
void PCHReader::ReadMacroRecord(uint64_t Offset) {
+ assert(PP && "Forgot to set Preprocessor ?");
+
// Keep track of where we are in the stream, then jump back there
// after reading this macro.
SavedStreamPosition SavedPosition(Stream);
@@ -930,7 +1055,7 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) {
SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[1]);
bool isUsed = Record[2];
- MacroInfo *MI = PP.AllocateMacroInfo(Loc);
+ MacroInfo *MI = PP->AllocateMacroInfo(Loc);
MI->setIsUsed(isUsed);
if (RecType == pch::PP_MACRO_FUNCTION_LIKE) {
@@ -947,11 +1072,11 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) {
if (isC99VarArgs) MI->setIsC99Varargs();
if (isGNUVarArgs) MI->setIsGNUVarargs();
MI->setArgumentList(MacroArgs.data(), MacroArgs.size(),
- PP.getPreprocessorAllocator());
+ PP->getPreprocessorAllocator());
}
// Finally, install the macro.
- PP.setMacroInfo(II, MI);
+ PP->setMacroInfo(II, MI);
// Remember that we saw this macro last so that we add the tokens that
// form its body to it.
@@ -1092,11 +1217,10 @@ PCHReader::ReadPCHBlock() {
return IgnorePCH;
}
- std::string TargetTriple(BlobStart, BlobLen);
- if (TargetTriple != PP.getTargetInfo().getTargetTriple()) {
- Diag(diag::warn_pch_target_triple)
- << TargetTriple << PP.getTargetInfo().getTargetTriple();
- return IgnorePCH;
+ if (Listener) {
+ std::string TargetTriple(BlobStart, BlobLen);
+ if (Listener->ReadTargetTriple(TargetTriple))
+ return IgnorePCH;
}
break;
}
@@ -1109,7 +1233,8 @@ PCHReader::ReadPCHBlock() {
(const unsigned char *)IdentifierTableData + Record[0],
(const unsigned char *)IdentifierTableData,
PCHIdentifierLookupTrait(*this));
- PP.getIdentifierTable().setExternalIdentifierLookup(this);
+ if (PP)
+ PP->getIdentifierTable().setExternalIdentifierLookup(this);
}
break;
@@ -1120,7 +1245,8 @@ PCHReader::ReadPCHBlock() {
}
IdentifierOffsets = (const uint32_t *)BlobStart;
IdentifiersLoaded.resize(Record[0]);
- PP.getHeaderSearchInfo().SetExternalLookup(this);
+ if (PP)
+ PP->getHeaderSearchInfo().SetExternalLookup(this);
break;
case pch::EXTERNAL_DEFINITIONS:
@@ -1176,14 +1302,14 @@ PCHReader::ReadPCHBlock() {
break;
case pch::PP_COUNTER_VALUE:
- if (!Record.empty())
- PP.setCounterValue(Record[0]);
+ if (!Record.empty() && Listener)
+ Listener->ReadCounter(Record[0]);
break;
case pch::SOURCE_LOCATION_OFFSETS:
SLocOffsets = (const uint32_t *)BlobStart;
TotalNumSLocEntries = Record[0];
- PP.getSourceManager().PreallocateSLocEntries(this,
+ SourceMgr.PreallocateSLocEntries(this,
TotalNumSLocEntries,
Record[1]);
break;
@@ -1197,7 +1323,7 @@ PCHReader::ReadPCHBlock() {
break;
case pch::STAT_CACHE:
- PP.getFileManager().setStatCache(
+ FileMgr.setStatCache(
new PCHStatCache((const unsigned char *)BlobStart + Record[0],
(const unsigned char *)BlobStart,
NumStatHits, NumStatMisses));
@@ -1287,10 +1413,10 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
// Clear out any preallocated source location entries, so that
// the source manager does not try to resolve them later.
- PP.getSourceManager().ClearPreallocatedSLocEntries();
+ SourceMgr.ClearPreallocatedSLocEntries();
// Remove the stat cache.
- PP.getFileManager().setStatCache(0);
+ FileMgr.setStatCache(0);
return IgnorePCH;
}
@@ -1303,71 +1429,82 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
break;
}
}
-
- // Load the translation unit declaration
- if (Context)
- ReadDeclRecord(DeclOffsets[0], 0);
// Check the predefines buffer.
if (CheckPredefinesBuffer(PCHPredefines, PCHPredefinesLen,
PCHPredefinesBufferID))
return IgnorePCH;
- // Initialization of builtins and library builtins occurs before the
- // PCH file is read, so there may be some identifiers that were
- // loaded into the IdentifierTable before we intercepted the
- // creation of identifiers. Iterate through the list of known
- // identifiers and determine whether we have to establish
- // preprocessor definitions or top-level identifier declaration
- // chains for those identifiers.
- //
- // We copy the IdentifierInfo pointers to a small vector first,
- // since de-serializing declarations or macro definitions can add
- // new entries into the identifier table, invalidating the
- // iterators.
- llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
- for (IdentifierTable::iterator Id = PP.getIdentifierTable().begin(),
- IdEnd = PP.getIdentifierTable().end();
- Id != IdEnd; ++Id)
- Identifiers.push_back(Id->second);
- PCHIdentifierLookupTable *IdTable
- = (PCHIdentifierLookupTable *)IdentifierLookupTable;
- for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
- IdentifierInfo *II = Identifiers[I];
- // Look in the on-disk hash table for an entry for
- PCHIdentifierLookupTrait Info(*this, II);
- std::pair<const char*, unsigned> Key(II->getName(), II->getLength());
- PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
- if (Pos == IdTable->end())
- continue;
-
- // Dereferencing the iterator has the effect of populating the
- // IdentifierInfo node with the various declarations it needs.
- (void)*Pos;
+ if (PP) {
+ // Initialization of builtins and library builtins occurs before the
+ // PCH file is read, so there may be some identifiers that were
+ // loaded into the IdentifierTable before we intercepted the
+ // creation of identifiers. Iterate through the list of known
+ // identifiers and determine whether we have to establish
+ // preprocessor definitions or top-level identifier declaration
+ // chains for those identifiers.
+ //
+ // We copy the IdentifierInfo pointers to a small vector first,
+ // since de-serializing declarations or macro definitions can add
+ // new entries into the identifier table, invalidating the
+ // iterators.
+ llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
+ for (IdentifierTable::iterator Id = PP->getIdentifierTable().begin(),
+ IdEnd = PP->getIdentifierTable().end();
+ Id != IdEnd; ++Id)
+ Identifiers.push_back(Id->second);
+ PCHIdentifierLookupTable *IdTable
+ = (PCHIdentifierLookupTable *)IdentifierLookupTable;
+ for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
+ IdentifierInfo *II = Identifiers[I];
+ // Look in the on-disk hash table for an entry for
+ PCHIdentifierLookupTrait Info(*this, II);
+ std::pair<const char*, unsigned> Key(II->getName(), II->getLength());
+ PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
+ if (Pos == IdTable->end())
+ continue;
+
+ // Dereferencing the iterator has the effect of populating the
+ // IdentifierInfo node with the various declarations it needs.
+ (void)*Pos;
+ }
}
- // Load the special types.
- if (Context) {
- Context->setBuiltinVaListType(
- GetType(SpecialTypes[pch::SPECIAL_TYPE_BUILTIN_VA_LIST]));
- if (unsigned Id = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID])
- Context->setObjCIdType(GetType(Id));
- if (unsigned Sel = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SELECTOR])
- Context->setObjCSelType(GetType(Sel));
- if (unsigned Proto = SpecialTypes[pch::SPECIAL_TYPE_OBJC_PROTOCOL])
- Context->setObjCProtoType(GetType(Proto));
- if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS])
- Context->setObjCClassType(GetType(Class));
- if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING])
- Context->setCFConstantStringType(GetType(String));
- if (unsigned FastEnum
- = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE])
- Context->setObjCFastEnumerationStateType(GetType(FastEnum));
- }
+ if (Context)
+ InitializeContext(*Context);
return Success;
}
+void PCHReader::InitializeContext(ASTContext &Ctx) {
+ Context = &Ctx;
+ assert(Context && "Passed null context!");
+
+ assert(PP && "Forgot to set Preprocessor ?");
+ PP->getIdentifierTable().setExternalIdentifierLookup(this);
+ PP->getHeaderSearchInfo().SetExternalLookup(this);
+
+ // Load the translation unit declaration
+ ReadDeclRecord(DeclOffsets[0], 0);
+
+ // Load the special types.
+ Context->setBuiltinVaListType(
+ GetType(SpecialTypes[pch::SPECIAL_TYPE_BUILTIN_VA_LIST]));
+ if (unsigned Id = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID])
+ Context->setObjCIdType(GetType(Id));
+ if (unsigned Sel = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SELECTOR])
+ Context->setObjCSelType(GetType(Sel));
+ if (unsigned Proto = SpecialTypes[pch::SPECIAL_TYPE_OBJC_PROTOCOL])
+ Context->setObjCProtoType(GetType(Proto));
+ if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS])
+ Context->setObjCClassType(GetType(Class));
+ if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING])
+ Context->setCFConstantStringType(GetType(String));
+ if (unsigned FastEnum
+ = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE])
+ Context->setObjCFastEnumerationStateType(GetType(FastEnum));
+}
+
/// \brief Retrieve the name of the original source file name
/// directly from the PCH file, without actually loading the PCH
/// file.
@@ -1465,73 +1602,60 @@ std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName) {
/// \returns true if the PCH file is unacceptable, false otherwise.
bool PCHReader::ParseLanguageOptions(
const llvm::SmallVectorImpl<uint64_t> &Record) {
- const LangOptions &LangOpts = PP.getLangOptions();
-#define PARSE_LANGOPT_BENIGN(Option) ++Idx
-#define PARSE_LANGOPT_IMPORTANT(Option, DiagID) \
- if (Record[Idx] != LangOpts.Option) { \
- Diag(DiagID) << (unsigned)Record[Idx] << LangOpts.Option; \
- return true; \
- } \
- ++Idx
-
- unsigned Idx = 0;
- PARSE_LANGOPT_BENIGN(Trigraphs);
- PARSE_LANGOPT_BENIGN(BCPLComment);
- PARSE_LANGOPT_BENIGN(DollarIdents);
- PARSE_LANGOPT_BENIGN(AsmPreprocessor);
- PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions);
- PARSE_LANGOPT_BENIGN(ImplicitInt);
- PARSE_LANGOPT_BENIGN(Digraphs);
- PARSE_LANGOPT_BENIGN(HexFloats);
- PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99);
- PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions);
- PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus);
- PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x);
- PARSE_LANGOPT_BENIGN(CXXOperatorName);
- PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c);
- PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2);
- PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi);
- PARSE_LANGOPT_BENIGN(PascalStrings);
- PARSE_LANGOPT_BENIGN(WritableStrings);
- PARSE_LANGOPT_IMPORTANT(LaxVectorConversions,
- diag::warn_pch_lax_vector_conversions);
- PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
- PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
- PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
- PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins);
- PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics,
- diag::warn_pch_thread_safe_statics);
- PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
- PARSE_LANGOPT_BENIGN(EmitAllDecls);
- PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
- PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking);
- PARSE_LANGOPT_IMPORTANT(HeinousExtensions,
- diag::warn_pch_heinous_extensions);
- // FIXME: Most of the options below are benign if the macro wasn't
- // used. Unfortunately, this means that a PCH compiled without
- // optimization can't be used with optimization turned on, even
- // though the only thing that changes is whether __OPTIMIZE__ was
- // defined... but if __OPTIMIZE__ never showed up in the header, it
- // doesn't matter. We could consider making this some special kind
- // of check.
- PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize);
- PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size);
- PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static);
- PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level);
- PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline);
- 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);
- if ((LangOpts.getGCMode() != 0) != (Record[Idx] != 0)) {
- Diag(diag::warn_pch_gc_mode)
- << (unsigned)Record[Idx] << LangOpts.getGCMode();
- return true;
+ if (Listener) {
+ LangOptions LangOpts;
+
+ #define PARSE_LANGOPT(Option) \
+ LangOpts.Option = Record[Idx]; \
+ ++Idx
+
+ unsigned Idx = 0;
+ PARSE_LANGOPT(Trigraphs);
+ PARSE_LANGOPT(BCPLComment);
+ PARSE_LANGOPT(DollarIdents);
+ PARSE_LANGOPT(AsmPreprocessor);
+ PARSE_LANGOPT(GNUMode);
+ PARSE_LANGOPT(ImplicitInt);
+ PARSE_LANGOPT(Digraphs);
+ PARSE_LANGOPT(HexFloats);
+ PARSE_LANGOPT(C99);
+ PARSE_LANGOPT(Microsoft);
+ PARSE_LANGOPT(CPlusPlus);
+ PARSE_LANGOPT(CPlusPlus0x);
+ PARSE_LANGOPT(CXXOperatorNames);
+ PARSE_LANGOPT(ObjC1);
+ PARSE_LANGOPT(ObjC2);
+ PARSE_LANGOPT(ObjCNonFragileABI);
+ PARSE_LANGOPT(PascalStrings);
+ PARSE_LANGOPT(WritableStrings);
+ PARSE_LANGOPT(LaxVectorConversions);
+ PARSE_LANGOPT(Exceptions);
+ PARSE_LANGOPT(NeXTRuntime);
+ PARSE_LANGOPT(Freestanding);
+ PARSE_LANGOPT(NoBuiltin);
+ PARSE_LANGOPT(ThreadsafeStatics);
+ PARSE_LANGOPT(Blocks);
+ PARSE_LANGOPT(EmitAllDecls);
+ PARSE_LANGOPT(MathErrno);
+ PARSE_LANGOPT(OverflowChecking);
+ PARSE_LANGOPT(HeinousExtensions);
+ PARSE_LANGOPT(Optimize);
+ PARSE_LANGOPT(OptimizeSize);
+ PARSE_LANGOPT(Static);
+ PARSE_LANGOPT(PICLevel);
+ PARSE_LANGOPT(GNUInline);
+ PARSE_LANGOPT(NoInline);
+ PARSE_LANGOPT(AccessControl);
+ PARSE_LANGOPT(CharIsSigned);
+ LangOpts.setGCMode((LangOptions::GCMode)Record[Idx]);
+ ++Idx;
+ LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx]);
+ ++Idx;
+ PARSE_LANGOPT(InstantiationDepth);
+ #undef PARSE_LANGOPT
+
+ return Listener->ReadLanguageOptions(LangOpts);
}
- ++Idx;
- PARSE_LANGOPT_BENIGN(getVisibilityMode());
- PARSE_LANGOPT_BENIGN(InstantiationDepth);
-#undef PARSE_LANGOPT_IRRELEVANT
-#undef PARSE_LANGOPT_BENIGN
return false;
}
@@ -1722,13 +1846,15 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return Context->getObjCQualifiedInterfaceType(ItfD, Protos.data(), NumProtos);
}
- case pch::TYPE_OBJC_QUALIFIED_ID: {
+ case pch::TYPE_OBJC_OBJECT_POINTER: {
unsigned Idx = 0;
+ ObjCInterfaceDecl *ItfD =
+ cast_or_null<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
unsigned NumProtos = Record[Idx++];
llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
for (unsigned I = 0; I != NumProtos; ++I)
Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
- return Context->getObjCQualifiedIdType(Protos.data(), NumProtos);
+ return Context->getObjCObjectPointerType(ItfD, Protos.data(), NumProtos);
}
}
// Suppress a GCC warning
@@ -2056,6 +2182,7 @@ IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
return 0;
}
+ assert(PP && "Forgot to set Preprocessor ?");
if (!IdentifiersLoaded[ID - 1]) {
uint32_t Offset = IdentifierOffsets[ID - 1];
const char *Str = IdentifierTableData + Offset;
@@ -2067,7 +2194,7 @@ IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
unsigned StrLen = (((unsigned) StrLenPtr[0])
| (((unsigned) StrLenPtr[1]) << 8)) - 1;
IdentifiersLoaded[ID - 1]
- = &PP.getIdentifierTable().get(Str, Str + StrLen);
+ = &PP->getIdentifierTable().get(Str, Str + StrLen);
}
return IdentifiersLoaded[ID - 1];
@@ -2170,15 +2297,14 @@ DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
}
DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) {
- return PP.getDiagnostics().Report(FullSourceLoc(Loc,
- PP.getSourceManager()),
- DiagID);
+ return Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
}
/// \brief Retrieve the identifier table associated with the
/// preprocessor.
IdentifierTable &PCHReader::getIdentifierTable() {
- return PP.getIdentifierTable();
+ assert(PP && "Forgot to set Preprocessor ?");
+ return PP->getIdentifierTable();
}
/// \brief Record that the given ID maps to the given switch-case
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp
index 6856623..3dd84c7 100644
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ b/lib/Frontend/PCHReaderDecl.cpp
@@ -80,8 +80,9 @@ void PCHDeclReader::VisitDecl(Decl *D) {
D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
D->setInvalidDecl(Record[Idx++]);
if (Record[Idx++])
- D->addAttr(Reader.ReadAttributes());
+ D->addAttr(*Reader.getContext(), Reader.ReadAttributes());
D->setImplicit(Record[Idx++]);
+ D->setUsed(Record[Idx++]);
D->setAccess((AccessSpecifier)Record[Idx++]);
}
@@ -156,6 +157,7 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
FD->setHasWrittenPrototype(Record[Idx++]);
FD->setDeleted(Record[Idx++]);
FD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ FD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++]));
// FIXME: C++ TemplateOrInstantiation
unsigned NumParams = Record[Idx++];
llvm::SmallVector<ParmVarDecl *, 16> Params;
diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp
index e6871e3..d096388 100644
--- a/lib/Frontend/PCHReaderStmt.cpp
+++ b/lib/Frontend/PCHReaderStmt.cpp
@@ -667,6 +667,7 @@ unsigned PCHStmtReader::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
E->setDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++])));
E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setByRef(Record[Idx++]);
+ E->setConstQualAdded(Record[Idx++]);
return 0;
}
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index 765fecb..3b1eb08 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -229,12 +229,14 @@ PCHTypeWriter::VisitObjCQualifiedInterfaceType(
Code = pch::TYPE_OBJC_QUALIFIED_INTERFACE;
}
-void PCHTypeWriter::VisitObjCQualifiedIdType(const ObjCQualifiedIdType *T) {
+void
+PCHTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
+ Writer.AddDeclRef(T->getDecl(), Record);
Record.push_back(T->getNumProtocols());
- for (ObjCQualifiedIdType::qual_iterator I = T->qual_begin(),
+ for (ObjCInterfaceType::qual_iterator I = T->qual_begin(),
E = T->qual_end(); I != E; ++I)
Writer.AddDeclRef(*I, Record);
- Code = pch::TYPE_OBJC_QUALIFIED_ID;
+ Code = pch::TYPE_OBJC_OBJECT_POINTER;
}
//===----------------------------------------------------------------------===//
@@ -407,7 +409,7 @@ void PCHWriter::WriteBlockInfoBlock() {
RECORD(TYPE_ENUM);
RECORD(TYPE_OBJC_INTERFACE);
RECORD(TYPE_OBJC_QUALIFIED_INTERFACE);
- RECORD(TYPE_OBJC_QUALIFIED_ID);
+ RECORD(TYPE_OBJC_OBJECT_POINTER);
// Statements and Exprs can occur in the Types block.
AddStmtsExprs(Stream, Record);
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp
index 6734661..44da4d7 100644
--- a/lib/Frontend/PCHWriterDecl.cpp
+++ b/lib/Frontend/PCHWriterDecl.cpp
@@ -82,6 +82,7 @@ void PCHDeclWriter::VisitDecl(Decl *D) {
Record.push_back(D->isInvalidDecl());
Record.push_back(D->hasAttrs());
Record.push_back(D->isImplicit());
+ Record.push_back(D->isUsed());
Record.push_back(D->getAccess());
}
@@ -156,6 +157,7 @@ void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
Record.push_back(D->hasWrittenPrototype());
Record.push_back(D->isDeleted());
Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record);
+ Writer.AddSourceLocation(D->getLocEnd(), Record);
// FIXME: C++ TemplateOrInstantiation
Record.push_back(D->param_size());
for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
@@ -360,6 +362,7 @@ void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
// know are true of all PARM_VAR_DECLs.
if (!D->hasAttrs() &&
!D->isImplicit() &&
+ !D->isUsed() &&
D->getAccess() == AS_none &&
D->getStorageClass() == 0 &&
!D->hasCXXDirectInitializer() && // Can params have this ever?
@@ -434,6 +437,7 @@ void PCHWriter::WriteDeclsBlockAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl (!?)
Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs
Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
+ Abv->Add(BitCodeAbbrevOp(0)); // isUsed
Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier
// NamedDecl
@@ -516,7 +520,7 @@ void PCHWriter::WriteDeclsBlock(ASTContext &Context) {
// If the declaration had any attributes, write them now.
if (D->hasAttrs())
- WriteAttributeRecord(D->getAttrs());
+ WriteAttributeRecord(D->getAttrs(Context));
// Flush any expressions that were written as part of this declaration.
FlushStmts();
diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp
index 73dea10..c63c03c 100644
--- a/lib/Frontend/PCHWriterStmt.cpp
+++ b/lib/Frontend/PCHWriterStmt.cpp
@@ -602,6 +602,7 @@ void PCHStmtWriter::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
Writer.AddDeclRef(E->getDecl(), Record);
Writer.AddSourceLocation(E->getLocation(), Record);
Record.push_back(E->isByRef());
+ Record.push_back(E->isConstQualAdded());
Code = pch::EXPR_BLOCK_DECL_REF;
}
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index 89d099c..d63d9cb 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -123,6 +123,8 @@ public:
}
void WriteLineInfo(unsigned LineNo, const char *Extra=0, unsigned ExtraLen=0);
+ void HandleNewlinesInToken(const char *TokStr, unsigned Len);
+
/// MacroDefined - This hook is called whenever a macro definition is seen.
void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI);
@@ -327,6 +329,29 @@ bool PrintPPOutputPPCallbacks::HandleFirstTokOnLine(Token &Tok) {
return true;
}
+void PrintPPOutputPPCallbacks::HandleNewlinesInToken(const char *TokStr,
+ unsigned Len) {
+ unsigned NumNewlines = 0;
+ for (; Len; --Len, ++TokStr) {
+ if (*TokStr != '\n' &&
+ *TokStr != '\r')
+ continue;
+
+ ++NumNewlines;
+
+ // If we have \n\r or \r\n, skip both and count as one line.
+ if (Len != 1 &&
+ (TokStr[1] == '\n' || TokStr[1] == '\r') &&
+ TokStr[0] != TokStr[1])
+ ++TokStr, --Len;
+ }
+
+ if (NumNewlines == 0) return;
+
+ CurLine += NumNewlines;
+}
+
+
namespace {
struct UnknownPragmaHandler : public PragmaHandler {
const char *Prefix;
@@ -382,9 +407,19 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
const char *TokPtr = Buffer;
unsigned Len = PP.getSpelling(Tok, TokPtr);
OS.write(TokPtr, Len);
+
+ // Tokens that can contain embedded newlines need to adjust our current
+ // line number.
+ if (Tok.getKind() == tok::comment)
+ Callbacks->HandleNewlinesInToken(TokPtr, Len);
} else {
std::string S = PP.getSpelling(Tok);
OS.write(&S[0], S.size());
+
+ // Tokens that can contain embedded newlines need to adjust our current
+ // line number.
+ if (Tok.getKind() == tok::comment)
+ Callbacks->HandleNewlinesInToken(&S[0], S.size());
}
Callbacks->SetEmittedTokensOnThisLine();
diff --git a/lib/Frontend/RewriteBlocks.cpp b/lib/Frontend/RewriteBlocks.cpp
index 8393574..d20d5cd 100644
--- a/lib/Frontend/RewriteBlocks.cpp
+++ b/lib/Frontend/RewriteBlocks.cpp
@@ -132,7 +132,7 @@ public:
if (const PointerType *PT = OCT->getAsPointerType()) {
if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
- isa<ObjCQualifiedIdType>(PT->getPointeeType()))
+ PT->getPointeeType()->isObjCQualifiedIdType())
return true;
}
return false;
diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp
index f382704..dce2710 100644
--- a/lib/Frontend/RewriteObjC.cpp
+++ b/lib/Frontend/RewriteObjC.cpp
@@ -356,7 +356,7 @@ namespace {
if (const PointerType *PT = OCT->getAsPointerType()) {
if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
- isa<ObjCQualifiedIdType>(PT->getPointeeType()))
+ PT->getPointeeType()->isObjCQualifiedIdType())
return true;
}
return false;
diff --git a/lib/Frontend/StmtXML.cpp b/lib/Frontend/StmtXML.cpp
index c861881..6ba0a28 100644
--- a/lib/Frontend/StmtXML.cpp
+++ b/lib/Frontend/StmtXML.cpp
@@ -28,8 +28,31 @@ namespace {
class VISIBILITY_HIDDEN StmtXML : public StmtVisitor<StmtXML> {
DocumentXML& Doc;
- static const char *getOpcodeStr(UnaryOperator::Opcode Op);
- static const char *getOpcodeStr(BinaryOperator::Opcode Op);
+ //static const char *getOpcodeStr(UnaryOperator::Opcode Op);
+ //static const char *getOpcodeStr(BinaryOperator::Opcode Op);
+
+
+ void addSpecialAttribute(const char* pName, StringLiteral* Str)
+ {
+ Doc.addAttribute(pName, Doc.escapeString(Str->getStrData(), Str->getByteLength()));
+ }
+
+ void addSpecialAttribute(const char* pName, SizeOfAlignOfExpr* S)
+ {
+ if (S->isArgumentType())
+ {
+ Doc.addAttribute(pName, S->getArgumentType());
+ }
+ }
+
+ void addSpecialAttribute(const char* pName, CXXTypeidExpr* S)
+ {
+ if (S->isTypeOperand())
+ {
+ Doc.addAttribute(pName, S->getTypeOperand());
+ }
+ }
+
public:
StmtXML(DocumentXML& doc)
@@ -39,12 +62,21 @@ namespace {
void DumpSubTree(Stmt *S) {
if (S)
{
- Doc.addSubNode(S->getStmtClassName());
- Doc.addLocationRange(S->getSourceRange());
- if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) {
- VisitDeclStmt(DS);
- } else {
- Visit(S);
+ Visit(S);
+ if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
+ {
+ for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
+ DI != DE; ++DI)
+ {
+ Doc.PrintDecl(*DI);
+ }
+ }
+ else
+ {
+ if (CXXConditionDeclExpr* CCDE = dyn_cast<CXXConditionDeclExpr>(S))
+ {
+ Doc.PrintDecl(CCDE->getVarDecl());
+ }
for (Stmt::child_iterator i = S->child_begin(), e = S->child_end(); i != e; ++i)
{
DumpSubTree(*i);
@@ -56,17 +88,46 @@ namespace {
}
}
- void DumpTypeExpr(const QualType& T)
- {
- Doc.addSubNode("TypeExpr");
- Doc.addTypeAttribute(T);
- Doc.toParent();
- }
- void DumpExpr(const Expr *Node) {
- Doc.addTypeAttribute(Node->getType());
- }
+#define NODE_XML( CLASS, NAME ) \
+ void Visit##CLASS(CLASS* S) \
+ { \
+ typedef CLASS tStmtType; \
+ Doc.addSubNode(NAME);
+
+#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, S->FN);
+#define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
+#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, S->FN);
+#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, S);
+#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocationRange(S->getSourceRange());
+
+#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = false; \
+ switch (S->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = true; \
+ switch (S->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
+#define END_ENUM_XML } }
+#define END_NODE_XML }
+
+#define ID_ATTRIBUTE_XML Doc.addAttribute("id", S);
+#define SUB_NODE_XML( CLASS )
+#define SUB_NODE_SEQUENCE_XML( CLASS )
+#define SUB_NODE_OPT_XML( CLASS )
+
+#include "clang/Frontend/StmtXML.def"
+
+#if (0)
// Stmts.
void VisitStmt(Stmt *Node);
void VisitDeclStmt(DeclStmt *Node);
@@ -105,13 +166,14 @@ namespace {
void VisitObjCKVCRefExpr(ObjCKVCRefExpr *Node);
void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
void VisitObjCSuperExpr(ObjCSuperExpr *Node);
+#endif
};
}
//===----------------------------------------------------------------------===//
// Stmt printing methods.
//===----------------------------------------------------------------------===//
-
+#if (0)
void StmtXML::VisitStmt(Stmt *Node)
{
// nothing special to do
@@ -396,7 +458,7 @@ void StmtXML::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
if (Node->isFreeIvar())
Doc.addAttribute("isFreeIvar", "1");
}
-
+#endif
//===----------------------------------------------------------------------===//
// Stmt method implementations
//===----------------------------------------------------------------------===//
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index 6699c65..d4c7e0f 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -640,9 +640,18 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
SourceLocation B = Info.getRange(i).getBegin();
SourceLocation E = Info.getRange(i).getEnd();
- std::pair<FileID, unsigned> BInfo=SM.getDecomposedInstantiationLoc(B);
-
+ B = SM.getInstantiationLoc(B);
E = SM.getInstantiationLoc(E);
+
+ // If the End location and the start location are the same and are a
+ // macro location, then the range was something that came from a macro
+ // expansion or _Pragma. If this is an object-like macro, the best we
+ // can do is to highlight the range. If this is a function-like
+ // macro, we'd also like to highlight the arguments.
+ if (B == E && Info.getRange(i).getEnd().isMacroID())
+ E = SM.getInstantiationRange(Info.getRange(i).getEnd()).second;
+
+ std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B);
std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E);
// If the start or end of the range is in another file, just discard
diff --git a/lib/Frontend/TypeXML.cpp b/lib/Frontend/TypeXML.cpp
new file mode 100644
index 0000000..f32fbbd
--- /dev/null
+++ b/lib/Frontend/TypeXML.cpp
@@ -0,0 +1,127 @@
+//===--- DocumentXML.cpp - XML document for ASTs --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the XML document class, which provides the means to
+// dump out the AST in a XML form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/DocumentXML.h"
+#include "clang/AST/TypeVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/Decl.h"
+
+namespace clang {
+ namespace XML {
+ namespace {
+
+//---------------------------------------------------------
+class TypeWriter : public TypeVisitor<TypeWriter>
+{
+ DocumentXML& Doc;
+
+public:
+ TypeWriter(DocumentXML& doc) : Doc(doc) {}
+
+#define NODE_XML( CLASS, NAME ) \
+ void Visit##CLASS(CLASS* T) \
+ { \
+ Doc.addSubNode(NAME);
+
+#define ID_ATTRIBUTE_XML // done by the Document class itself
+#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN);
+#define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
+#define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context")
+#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN);
+
+#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = false; \
+ switch (T->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = true; \
+ switch (T->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
+#define END_ENUM_XML } }
+#define END_NODE_XML }
+
+#include "clang/Frontend/TypeXML.def"
+
+};
+
+//---------------------------------------------------------
+ } // anon clang
+ } // NS XML
+
+//---------------------------------------------------------
+class DocumentXML::TypeAdder : public TypeVisitor<DocumentXML::TypeAdder>
+{
+ DocumentXML& Doc;
+
+ void addIfType(const Type* pType)
+ {
+ Doc.addTypeRecursively(pType);
+ }
+
+ void addIfType(const QualType& pType)
+ {
+ Doc.addTypeRecursively(pType);
+ }
+
+ template<class T> void addIfType(T) {}
+
+public:
+ TypeAdder(DocumentXML& doc) : Doc(doc) {}
+
+#define NODE_XML( CLASS, NAME ) \
+ void Visit##CLASS(CLASS* T) \
+ {
+
+#define ID_ATTRIBUTE_XML
+#define TYPE_ATTRIBUTE_XML( FN ) Doc.addTypeRecursively(T->FN);
+#define CONTEXT_ATTRIBUTE_XML( FN )
+#define ATTRIBUTE_XML( FN, NAME ) addIfType(T->FN);
+#define ATTRIBUTE_OPT_XML( FN, NAME )
+#define ATTRIBUTE_ENUM_XML( FN, NAME )
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME )
+#define ENUM_XML( VALUE, NAME )
+#define END_ENUM_XML
+#define END_NODE_XML }
+
+#include "clang/Frontend/TypeXML.def"
+};
+
+//---------------------------------------------------------
+void DocumentXML::addParentTypes(const Type* pType)
+{
+ TypeAdder(*this).Visit(const_cast<Type*>(pType));
+}
+
+//---------------------------------------------------------
+void DocumentXML::writeTypeToXML(const Type* pType)
+{
+ XML::TypeWriter(*this).Visit(const_cast<Type*>(pType));
+}
+
+//---------------------------------------------------------
+void DocumentXML::writeTypeToXML(const QualType& pType)
+{
+ XML::TypeWriter(*this).VisitQualType(const_cast<QualType*>(&pType));
+}
+
+//---------------------------------------------------------
+} // NS clang
+
OpenPOWER on IntegriCloud