summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2009-11-18 14:59:57 +0000
committerrdivacky <rdivacky@FreeBSD.org>2009-11-18 14:59:57 +0000
commit741c13ecc20fb35b836ad690aeecd402f002d654 (patch)
tree60a1694bec5a44d15456acc880cb2f91619f66aa /tools
parentb3a51061b1b9c4add078237850649f7c9efb13ab (diff)
downloadFreeBSD-src-741c13ecc20fb35b836ad690aeecd402f002d654.zip
FreeBSD-src-741c13ecc20fb35b836ad690aeecd402f002d654.tar.gz
Update clang to r89205.
Diffstat (limited to 'tools')
-rw-r--r--tools/CIndex/CIndex.cpp597
-rw-r--r--tools/CIndex/CIndex.exports9
-rw-r--r--tools/CIndex/CMakeLists.txt2
-rw-r--r--tools/CIndex/Makefile2
-rw-r--r--tools/CMakeLists.txt4
-rw-r--r--tools/c-index-test/c-index-test.c352
-rw-r--r--tools/clang-cc/CMakeLists.txt1
-rw-r--r--tools/clang-cc/Options.cpp1330
-rw-r--r--tools/clang-cc/Options.h57
-rw-r--r--tools/clang-cc/clang-cc.cpp2391
-rw-r--r--tools/driver/driver.cpp10
11 files changed, 2399 insertions, 2356 deletions
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp
index 4798e28..ebdba29 100644
--- a/tools/CIndex/CIndex.cpp
+++ b/tools/CIndex/CIndex.cpp
@@ -16,12 +16,15 @@
#include "clang/Index/Indexer.h"
#include "clang/Index/ASTLocation.h"
#include "clang/Index/Utils.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/ASTUnit.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -31,6 +34,7 @@
#include <cstdio>
#include <vector>
+#include <sstream>
#ifdef LLVM_ON_WIN32
#define WIN32_LEAN_AND_MEAN
@@ -137,8 +141,25 @@ public:
I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
Visit(*I);
}
- void VisitTypedefDecl(TypedefDecl *ND) {
- Call(CXCursor_TypedefDecl, ND);
+
+ void VisitFunctionDecl(FunctionDecl *ND) {
+ Call(ND->isThisDeclarationADefinition() ? CXCursor_FunctionDefn
+ : CXCursor_FunctionDecl, ND);
+ }
+ void VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
+ Call(CXCursor_ObjCCategoryDecl, ND);
+ }
+ void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *ND) {
+ Call(CXCursor_ObjCCategoryDefn, ND);
+ }
+ void VisitObjCImplementationDecl(ObjCImplementationDecl *ND) {
+ Call(CXCursor_ObjCClassDefn, ND);
+ }
+ void VisitObjCInterfaceDecl(ObjCInterfaceDecl *ND) {
+ Call(CXCursor_ObjCInterfaceDecl, ND);
+ }
+ void VisitObjCProtocolDecl(ObjCProtocolDecl *ND) {
+ Call(CXCursor_ObjCProtocolDecl, ND);
}
void VisitTagDecl(TagDecl *ND) {
switch (ND->getTagKind()) {
@@ -156,29 +177,14 @@ public:
break;
}
}
+ void VisitTypedefDecl(TypedefDecl *ND) {
+ Call(CXCursor_TypedefDecl, ND);
+ }
void VisitVarDecl(VarDecl *ND) {
Call(CXCursor_VarDecl, ND);
- }
- void VisitFunctionDecl(FunctionDecl *ND) {
- Call(ND->isThisDeclarationADefinition() ? CXCursor_FunctionDefn
- : CXCursor_FunctionDecl, ND);
- }
- void VisitObjCInterfaceDecl(ObjCInterfaceDecl *ND) {
- Call(CXCursor_ObjCInterfaceDecl, ND);
- }
- void VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
- Call(CXCursor_ObjCCategoryDecl, ND);
- }
- void VisitObjCProtocolDecl(ObjCProtocolDecl *ND) {
- Call(CXCursor_ObjCProtocolDecl, ND);
- }
- void VisitObjCImplementationDecl(ObjCImplementationDecl *ND) {
- Call(CXCursor_ObjCClassDefn, ND);
- }
- void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *ND) {
- Call(CXCursor_ObjCCategoryDefn, ND);
- }
+ }
};
+
// Declaration visitor.
class CDeclVisitor : public DeclVisitor<CDeclVisitor> {
@@ -327,6 +333,11 @@ const llvm::sys::Path& CIndexer::getClangPath() {
GetModuleFileNameA((HINSTANCE)mbi.AllocationBase, path, MAX_PATH);
llvm::sys::Path CIndexPath(path);
+
+ CIndexPath.eraseComponent();
+ CIndexPath.appendComponent("clang");
+ CIndexPath.appendSuffix("exe");
+ CIndexPath.makeAbsolute();
#else
// This silly cast below avoids a C++ warning.
Dl_info info;
@@ -334,13 +345,13 @@ const llvm::sys::Path& CIndexer::getClangPath() {
assert(0 && "Call to dladdr() failed");
llvm::sys::Path CIndexPath(info.dli_fname);
-#endif
// We now have the CIndex directory, locate clang relative to it.
CIndexPath.eraseComponent();
CIndexPath.eraseComponent();
CIndexPath.appendComponent("bin");
CIndexPath.appendComponent("clang");
+#endif
// Cache our result.
ClangPath = CIndexPath;
@@ -349,6 +360,82 @@ const llvm::sys::Path& CIndexer::getClangPath() {
}
+static SourceLocation getLocationFromCursor(CXCursor C,
+ SourceManager &SourceMgr,
+ NamedDecl *ND) {
+ if (clang_isReference(C.kind)) {
+ switch (C.kind) {
+ case CXCursor_ObjCClassRef: {
+ if (isa<ObjCInterfaceDecl>(ND)) {
+ // FIXME: This is a hack (storing the parent decl in the stmt slot).
+ NamedDecl *parentDecl = static_cast<NamedDecl *>(C.stmt);
+ return parentDecl->getLocation();
+ }
+ ObjCCategoryDecl *OID = dyn_cast<ObjCCategoryDecl>(ND);
+ assert(OID && "clang_getCursorLine(): Missing category decl");
+ return OID->getClassInterface()->getLocation();
+ }
+ case CXCursor_ObjCSuperClassRef: {
+ ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND);
+ assert(OID && "clang_getCursorLine(): Missing interface decl");
+ return OID->getSuperClassLoc();
+ }
+ case CXCursor_ObjCProtocolRef: {
+ ObjCProtocolDecl *OID = dyn_cast<ObjCProtocolDecl>(ND);
+ assert(OID && "clang_getCursorLine(): Missing protocol decl");
+ return OID->getLocation();
+ }
+ case CXCursor_ObjCSelectorRef: {
+ ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(
+ static_cast<Stmt *>(C.stmt));
+ assert(OME && "clang_getCursorLine(): Missing message expr");
+ return OME->getLeftLoc(); /* FIXME: should be a range */
+ }
+ case CXCursor_VarRef:
+ case CXCursor_FunctionRef:
+ case CXCursor_EnumConstantRef: {
+ DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(
+ static_cast<Stmt *>(C.stmt));
+ assert(DRE && "clang_getCursorLine(): Missing decl ref expr");
+ return DRE->getLocation();
+ }
+ default:
+ return SourceLocation();
+ }
+ } else { // We have a declaration or a definition.
+ SourceLocation SLoc;
+ switch (ND->getKind()) {
+ case Decl::ObjCInterface: {
+ SLoc = dyn_cast<ObjCInterfaceDecl>(ND)->getClassLoc();
+ break;
+ }
+ case Decl::ObjCProtocol: {
+ SLoc = ND->getLocation(); /* FIXME: need to get the name location. */
+ break;
+ }
+ default: {
+ SLoc = ND->getLocation();
+ break;
+ }
+ }
+ if (SLoc.isInvalid())
+ return SourceLocation();
+ return SourceMgr.getSpellingLoc(SLoc); // handles macro instantiations.
+ }
+}
+
+static CXString createCXString(const char *String, bool DupString = false) {
+ CXString Str;
+ if (DupString) {
+ Str.Spelling = strdup(String);
+ Str.MustFreeString = 1;
+ } else {
+ Str.Spelling = String;
+ Str.MustFreeString = 0;
+ }
+ return Str;
+}
+
extern "C" {
CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
@@ -384,7 +471,7 @@ CXTranslationUnit clang_createTranslationUnit(
CXXIdx->getOnlyLocalDecls(),
/* UseBumpAllocator = */ true);
- if (!ErrMsg.empty())
+ if (CXXIdx->getDisplayDiagnostics() && !ErrMsg.empty())
llvm::errs() << "clang_createTranslationUnit: " << ErrMsg << '\n';
return TU;
@@ -447,7 +534,7 @@ CXTranslationUnit clang_createTranslationUnitFromSourceFile(
/* redirects */ !CXXIdx->getDisplayDiagnostics() ? &Redirects[0] : NULL,
/* secondsToWait */ 0, /* memoryLimits */ 0, &ErrMsg);
- if (!ErrMsg.empty()) {
+ if (CXXIdx->getDisplayDiagnostics() && !ErrMsg.empty()) {
llvm::errs() << "clang_createTranslationUnitFromSourceFile: " << ErrMsg
<< '\n' << "Arguments: \n";
for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
@@ -473,11 +560,11 @@ void clang_disposeTranslationUnit(
delete static_cast<ASTUnit *>(CTUnit);
}
-const char *clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit)
+CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit)
{
assert(CTUnit && "Passed null CXTranslationUnit");
ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit);
- return CXXUnit->getOriginalSourceFileName().c_str();
+ return createCXString(CXXUnit->getOriginalSourceFileName().c_str(), true);
}
void clang_loadTranslationUnit(CXTranslationUnit CTUnit,
@@ -542,24 +629,24 @@ CXEntity clang_getEntityFromDecl(CXDecl)
{
return 0;
}
-const char *clang_getDeclSpelling(CXDecl AnonDecl)
+CXString clang_getDeclSpelling(CXDecl AnonDecl)
{
assert(AnonDecl && "Passed null CXDecl");
NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
-
- if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND)) {
- return OMD->getSelector().getAsString().c_str();
- }
+
+ if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))
+ return createCXString(OMD->getSelector().getAsString().c_str(), true);
+
if (ObjCCategoryImplDecl *CIMP = dyn_cast<ObjCCategoryImplDecl>(ND))
// No, this isn't the same as the code below. getIdentifier() is non-virtual
// and returns different names. NamedDecl returns the class name and
// ObjCCategoryImplDecl returns the category name.
- return CIMP->getIdentifier()->getNameStart();
-
+ return createCXString(CIMP->getIdentifier()->getNameStart());
+
if (ND->getIdentifier())
- return ND->getIdentifier()->getNameStart();
- else
- return "";
+ return createCXString(ND->getIdentifier()->getNameStart());
+
+ return createCXString("");
}
unsigned clang_getDeclLine(CXDecl AnonDecl)
@@ -617,36 +704,38 @@ time_t clang_getFileTime(CXFile SFile) {
return FEnt->getModificationTime();
}
-const char *clang_getCursorSpelling(CXCursor C)
+CXString clang_getCursorSpelling(CXCursor C)
{
assert(C.decl && "CXCursor has null decl");
NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
-
+
if (clang_isReference(C.kind)) {
switch (C.kind) {
case CXCursor_ObjCSuperClassRef: {
ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND);
assert(OID && "clang_getCursorLine(): Missing interface decl");
- return OID->getSuperClass()->getIdentifier()->getNameStart();
+ return createCXString(OID->getSuperClass()->getIdentifier()
+ ->getNameStart());
}
case CXCursor_ObjCClassRef: {
- if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND)) {
- return OID->getIdentifier()->getNameStart();
- }
- ObjCCategoryDecl *OID = dyn_cast<ObjCCategoryDecl>(ND);
- assert(OID && "clang_getCursorLine(): Missing category decl");
- return OID->getClassInterface()->getIdentifier()->getNameStart();
+ if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND))
+ return createCXString(OID->getIdentifier()->getNameStart());
+
+ ObjCCategoryDecl *OCD = dyn_cast<ObjCCategoryDecl>(ND);
+ assert(OCD && "clang_getCursorLine(): Missing category decl");
+ return createCXString(OCD->getClassInterface()->getIdentifier()
+ ->getNameStart());
}
case CXCursor_ObjCProtocolRef: {
ObjCProtocolDecl *OID = dyn_cast<ObjCProtocolDecl>(ND);
assert(OID && "clang_getCursorLine(): Missing protocol decl");
- return OID->getIdentifier()->getNameStart();
+ return createCXString(OID->getIdentifier()->getNameStart());
}
case CXCursor_ObjCSelectorRef: {
ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(
static_cast<Stmt *>(C.stmt));
assert(OME && "clang_getCursorLine(): Missing message expr");
- return OME->getSelector().getAsString().c_str();
+ return createCXString(OME->getSelector().getAsString().c_str(), true);
}
case CXCursor_VarRef:
case CXCursor_FunctionRef:
@@ -654,10 +743,10 @@ const char *clang_getCursorSpelling(CXCursor C)
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(
static_cast<Stmt *>(C.stmt));
assert(DRE && "clang_getCursorLine(): Missing decl ref expr");
- return DRE->getDecl()->getIdentifier()->getNameStart();
+ return createCXString(DRE->getDecl()->getIdentifier()->getNameStart());
}
default:
- return "<not implemented>";
+ return createCXString("<not implemented>");
}
}
return clang_getDeclSpelling(C.decl);
@@ -786,6 +875,18 @@ CXCursor clang_getCursor(CXTranslationUnit CTUnit, const char *source_name,
return C;
}
+CXCursor clang_getNullCursor(void) {
+ CXCursor C;
+ C.kind = CXCursor_InvalidFile;
+ C.decl = NULL;
+ C.stmt = NULL;
+ return C;
+}
+
+unsigned clang_equalCursors(CXCursor X, CXCursor Y) {
+ return X.kind == Y.kind && X.decl == Y.decl && X.stmt == Y.stmt;
+}
+
CXCursor clang_getCursorFromDecl(CXDecl AnonDecl)
{
assert(AnonDecl && "Passed null CXDecl");
@@ -856,71 +957,6 @@ CXDecl clang_getCursorDecl(CXCursor C)
return 0;
}
-
-static SourceLocation getLocationFromCursor(CXCursor C,
- SourceManager &SourceMgr,
- NamedDecl *ND) {
- if (clang_isReference(C.kind)) {
- switch (C.kind) {
- case CXCursor_ObjCClassRef: {
- if (isa<ObjCInterfaceDecl>(ND)) {
- // FIXME: This is a hack (storing the parent decl in the stmt slot).
- NamedDecl *parentDecl = static_cast<NamedDecl *>(C.stmt);
- return parentDecl->getLocation();
- }
- ObjCCategoryDecl *OID = dyn_cast<ObjCCategoryDecl>(ND);
- assert(OID && "clang_getCursorLine(): Missing category decl");
- return OID->getClassInterface()->getLocation();
- }
- case CXCursor_ObjCSuperClassRef: {
- ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND);
- assert(OID && "clang_getCursorLine(): Missing interface decl");
- return OID->getSuperClassLoc();
- }
- case CXCursor_ObjCProtocolRef: {
- ObjCProtocolDecl *OID = dyn_cast<ObjCProtocolDecl>(ND);
- assert(OID && "clang_getCursorLine(): Missing protocol decl");
- return OID->getLocation();
- }
- case CXCursor_ObjCSelectorRef: {
- ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(
- static_cast<Stmt *>(C.stmt));
- assert(OME && "clang_getCursorLine(): Missing message expr");
- return OME->getLeftLoc(); /* FIXME: should be a range */
- }
- case CXCursor_VarRef:
- case CXCursor_FunctionRef:
- case CXCursor_EnumConstantRef: {
- DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(
- static_cast<Stmt *>(C.stmt));
- assert(DRE && "clang_getCursorLine(): Missing decl ref expr");
- return DRE->getLocation();
- }
- default:
- return SourceLocation();
- }
- } else { // We have a declaration or a definition.
- SourceLocation SLoc;
- switch (ND->getKind()) {
- case Decl::ObjCInterface: {
- SLoc = dyn_cast<ObjCInterfaceDecl>(ND)->getClassLoc();
- break;
- }
- case Decl::ObjCProtocol: {
- SLoc = ND->getLocation(); /* FIXME: need to get the name location. */
- break;
- }
- default: {
- SLoc = ND->getLocation();
- break;
- }
- }
- if (SLoc.isInvalid())
- return SourceLocation();
- return SourceMgr.getSpellingLoc(SLoc); // handles macro instantiations.
- }
-}
-
unsigned clang_getCursorLine(CXCursor C)
{
assert(C.decl && "CXCursor has null decl");
@@ -931,6 +967,17 @@ unsigned clang_getCursorLine(CXCursor C)
return SourceMgr.getSpellingLineNumber(SLoc);
}
+// Access string.
+const char *clang_getCString(CXString string) {
+ return string.Spelling;
+}
+
+// Free CXString.
+void clang_disposeString(CXString string) {
+ if (string.MustFreeString)
+ free((void*)string.Spelling);
+}
+
unsigned clang_getCursorColumn(CXCursor C)
{
assert(C.decl && "CXCursor has null decl");
@@ -947,8 +994,11 @@ const char *clang_getCursorSource(CXCursor C)
SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
SourceLocation SLoc = getLocationFromCursor(C, SourceMgr, ND);
- if (SLoc.isFileID())
- return SourceMgr.getBufferName(SLoc);
+
+ if (SLoc.isFileID()) {
+ const char *bufferName = SourceMgr.getBufferName(SLoc);
+ return bufferName[0] == '<' ? NULL : bufferName;
+ }
// Retrieve the file in which the macro was instantiated, then provide that
// buffer name.
@@ -993,5 +1043,318 @@ void clang_getDefinitionSpellingAndExtent(CXCursor C,
*endColumn = SM.getSpellingColumnNumber(Body->getRBracLoc());
}
+enum CXCompletionChunkKind
+clang_getCompletionChunkKind(CXCompletionString completion_string,
+ unsigned chunk_number) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ if (!CCStr || chunk_number >= CCStr->size())
+ return CXCompletionChunk_Text;
+
+ switch ((*CCStr)[chunk_number].Kind) {
+ case CodeCompletionString::CK_TypedText:
+ return CXCompletionChunk_TypedText;
+ case CodeCompletionString::CK_Text:
+ return CXCompletionChunk_Text;
+ case CodeCompletionString::CK_Optional:
+ return CXCompletionChunk_Optional;
+ case CodeCompletionString::CK_Placeholder:
+ return CXCompletionChunk_Placeholder;
+ case CodeCompletionString::CK_Informative:
+ return CXCompletionChunk_Informative;
+ case CodeCompletionString::CK_CurrentParameter:
+ return CXCompletionChunk_CurrentParameter;
+ case CodeCompletionString::CK_LeftParen:
+ return CXCompletionChunk_LeftParen;
+ case CodeCompletionString::CK_RightParen:
+ return CXCompletionChunk_RightParen;
+ case CodeCompletionString::CK_LeftBracket:
+ return CXCompletionChunk_LeftBracket;
+ case CodeCompletionString::CK_RightBracket:
+ return CXCompletionChunk_RightBracket;
+ case CodeCompletionString::CK_LeftBrace:
+ return CXCompletionChunk_LeftBrace;
+ case CodeCompletionString::CK_RightBrace:
+ return CXCompletionChunk_RightBrace;
+ case CodeCompletionString::CK_LeftAngle:
+ return CXCompletionChunk_LeftAngle;
+ case CodeCompletionString::CK_RightAngle:
+ return CXCompletionChunk_RightAngle;
+ case CodeCompletionString::CK_Comma:
+ return CXCompletionChunk_Comma;
+ }
+
+ // Should be unreachable, but let's be careful.
+ return CXCompletionChunk_Text;
+}
+
+const char *clang_getCompletionChunkText(CXCompletionString completion_string,
+ unsigned chunk_number) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ if (!CCStr || chunk_number >= CCStr->size())
+ return 0;
+
+ switch ((*CCStr)[chunk_number].Kind) {
+ case CodeCompletionString::CK_TypedText:
+ case CodeCompletionString::CK_Text:
+ case CodeCompletionString::CK_Placeholder:
+ case CodeCompletionString::CK_CurrentParameter:
+ case CodeCompletionString::CK_Informative:
+ case CodeCompletionString::CK_LeftParen:
+ case CodeCompletionString::CK_RightParen:
+ case CodeCompletionString::CK_LeftBracket:
+ case CodeCompletionString::CK_RightBracket:
+ case CodeCompletionString::CK_LeftBrace:
+ case CodeCompletionString::CK_RightBrace:
+ case CodeCompletionString::CK_LeftAngle:
+ case CodeCompletionString::CK_RightAngle:
+ case CodeCompletionString::CK_Comma:
+ return (*CCStr)[chunk_number].Text;
+
+ case CodeCompletionString::CK_Optional:
+ // Note: treated as an empty text block.
+ return 0;
+ }
+
+ // Should be unreachable, but let's be careful.
+ return 0;
+}
+
+CXCompletionString
+clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
+ unsigned chunk_number) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ if (!CCStr || chunk_number >= CCStr->size())
+ return 0;
+
+ switch ((*CCStr)[chunk_number].Kind) {
+ case CodeCompletionString::CK_TypedText:
+ case CodeCompletionString::CK_Text:
+ case CodeCompletionString::CK_Placeholder:
+ case CodeCompletionString::CK_CurrentParameter:
+ case CodeCompletionString::CK_Informative:
+ case CodeCompletionString::CK_LeftParen:
+ case CodeCompletionString::CK_RightParen:
+ case CodeCompletionString::CK_LeftBracket:
+ case CodeCompletionString::CK_RightBracket:
+ case CodeCompletionString::CK_LeftBrace:
+ case CodeCompletionString::CK_RightBrace:
+ case CodeCompletionString::CK_LeftAngle:
+ case CodeCompletionString::CK_RightAngle:
+ case CodeCompletionString::CK_Comma:
+ return 0;
+
+ case CodeCompletionString::CK_Optional:
+ // Note: treated as an empty text block.
+ return (*CCStr)[chunk_number].Optional;
+ }
+
+ // Should be unreachable, but let's be careful.
+ return 0;
+}
+
+unsigned clang_getNumCompletionChunks(CXCompletionString completion_string) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ return CCStr? CCStr->size() : 0;
+}
+static CXCursorKind parseResultKind(llvm::StringRef Str) {
+ return llvm::StringSwitch<CXCursorKind>(Str)
+ .Case("Typedef", CXCursor_TypedefDecl)
+ .Case("Struct", CXCursor_StructDecl)
+ .Case("Union", CXCursor_UnionDecl)
+ .Case("Class", CXCursor_ClassDecl)
+ .Case("Enum", CXCursor_EnumDecl)
+ .Case("Field", CXCursor_FieldDecl)
+ .Case("EnumConstant", CXCursor_EnumConstantDecl)
+ .Case("Function", CXCursor_FunctionDecl)
+ // FIXME: Hacks here to make C++ member functions look like C functions
+ .Case("CXXMethod", CXCursor_FunctionDecl)
+ .Case("CXXConstructor", CXCursor_FunctionDecl)
+ .Case("CXXDestructor", CXCursor_FunctionDecl)
+ .Case("CXXConversion", CXCursor_FunctionDecl)
+ .Case("Var", CXCursor_VarDecl)
+ .Case("ParmVar", CXCursor_ParmDecl)
+ .Case("ObjCInterface", CXCursor_ObjCInterfaceDecl)
+ .Case("ObjCCategory", CXCursor_ObjCCategoryDecl)
+ .Case("ObjCProtocol", CXCursor_ObjCProtocolDecl)
+ .Case("ObjCProperty", CXCursor_ObjCPropertyDecl)
+ .Case("ObjCIvar", CXCursor_ObjCIvarDecl)
+ .Case("ObjCInstanceMethod", CXCursor_ObjCInstanceMethodDecl)
+ .Case("ObjCClassMethod", CXCursor_ObjCClassMethodDecl)
+ .Default(CXCursor_NotImplemented);
+}
+
+void clang_codeComplete(CXIndex CIdx,
+ const char *source_filename,
+ int num_command_line_args,
+ const char **command_line_args,
+ const char *complete_filename,
+ unsigned complete_line,
+ unsigned complete_column,
+ CXCompletionIterator completion_iterator,
+ CXClientData client_data) {
+ // The indexer, which is mainly used to determine where diagnostics go.
+ CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
+
+ // Build up the arguments for invoking 'clang'.
+ std::vector<const char *> argv;
+
+ // First add the complete path to the 'clang' executable.
+ llvm::sys::Path ClangPath = CXXIdx->getClangPath();
+ argv.push_back(ClangPath.c_str());
+
+ // Add the '-fsyntax-only' argument so that we only perform a basic
+ // syntax check of the code.
+ argv.push_back("-fsyntax-only");
+
+ // Add the appropriate '-code-completion-at=file:line:column' argument
+ // to perform code completion, with an "-Xclang" preceding it.
+ std::string code_complete_at;
+ code_complete_at += "-code-completion-at=";
+ code_complete_at += complete_filename;
+ code_complete_at += ":";
+ code_complete_at += llvm::utostr(complete_line);
+ code_complete_at += ":";
+ code_complete_at += llvm::utostr(complete_column);
+ argv.push_back("-Xclang");
+ argv.push_back(code_complete_at.c_str());
+ argv.push_back("-Xclang");
+ argv.push_back("-code-completion-debug-printer=0");
+
+ // Add the source file name (FIXME: later, we'll want to build temporary
+ // file from the buffer, or just feed the source text via standard input).
+ if (source_filename)
+ argv.push_back(source_filename);
+
+ // Process the compiler options, stripping off '-o', '-c', '-fsyntax-only'.
+ for (int i = 0; i < num_command_line_args; ++i)
+ if (const char *arg = command_line_args[i]) {
+ if (strcmp(arg, "-o") == 0) {
+ ++i; // Also skip the matching argument.
+ continue;
+ }
+ if (strcmp(arg, "-emit-ast") == 0 ||
+ strcmp(arg, "-c") == 0 ||
+ strcmp(arg, "-fsyntax-only") == 0) {
+ continue;
+ }
+
+ // Keep the argument.
+ argv.push_back(arg);
+ }
+
+ // Add the null terminator.
+ argv.push_back(NULL);
+
+ // Generate a temporary name for the AST file.
+ char tmpFile[L_tmpnam];
+ char *tmpFileName = tmpnam(tmpFile);
+ llvm::sys::Path ResultsFile(tmpFileName);
+
+ // Invoke 'clang'.
+ llvm::sys::Path DevNull; // leave empty, causes redirection to /dev/null
+ // on Unix or NUL (Windows).
+ std::string ErrMsg;
+ const llvm::sys::Path *Redirects[] = { &DevNull, &ResultsFile, &DevNull, 0 };
+ llvm::sys::Program::ExecuteAndWait(ClangPath, &argv[0], /* env */ NULL,
+ /* redirects */ &Redirects[0],
+ /* secondsToWait */ 0,
+ /* memoryLimits */ 0, &ErrMsg);
+
+ if (CXXIdx->getDisplayDiagnostics() && !ErrMsg.empty()) {
+ llvm::errs() << "clang_codeComplete: " << ErrMsg
+ << '\n' << "Arguments: \n";
+ for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
+ I!=E; ++I) {
+ if (*I)
+ llvm::errs() << ' ' << *I << '\n';
+ }
+ llvm::errs() << '\n';
+ }
+
+ // Parse the resulting source file to find code-completion results.
+ using llvm::MemoryBuffer;
+ using llvm::StringRef;
+ if (MemoryBuffer *F = MemoryBuffer::getFile(ResultsFile.c_str())) {
+ StringRef Buffer = F->getBuffer();
+ do {
+ StringRef::size_type CompletionIdx = Buffer.find("COMPLETION:");
+ StringRef::size_type OverloadIdx = Buffer.find("OVERLOAD:");
+ if (CompletionIdx == StringRef::npos && OverloadIdx == StringRef::npos)
+ break;
+
+ if (OverloadIdx < CompletionIdx) {
+ // Parse an overload result.
+ Buffer = Buffer.substr(OverloadIdx);
+
+ // Skip past the OVERLOAD:
+ Buffer = Buffer.substr(Buffer.find(':') + 1);
+
+ // Find the entire completion string.
+ StringRef::size_type EOL = Buffer.find_first_of("\n\r");
+ if (EOL == StringRef::npos)
+ continue;
+
+ StringRef Line = Buffer.substr(0, EOL);
+ Buffer = Buffer.substr(EOL + 1);
+ CodeCompletionString *CCStr = CodeCompletionString::Deserialize(Line);
+ if (!CCStr || CCStr->empty())
+ continue;
+
+ // Vend the code-completion result to the caller.
+ CXCompletionResult Result;
+ Result.CursorKind = CXCursor_NotImplemented;
+ Result.CompletionString = CCStr;
+ if (completion_iterator)
+ completion_iterator(&Result, client_data);
+ delete CCStr;
+
+ continue;
+ }
+
+ // Parse a completion result.
+ Buffer = Buffer.substr(CompletionIdx);
+
+ // Skip past the COMPLETION:
+ Buffer = Buffer.substr(Buffer.find(':') + 1);
+
+ // Get the rank
+ unsigned Rank = 0;
+ StringRef::size_type AfterRank = Buffer.find(':');
+ Buffer.substr(0, AfterRank).getAsInteger(10, Rank);
+ Buffer = Buffer.substr(AfterRank + 1);
+
+ // Get the kind of result.
+ StringRef::size_type AfterKind = Buffer.find(':');
+ StringRef Kind = Buffer.substr(0, AfterKind);
+ Buffer = Buffer.substr(AfterKind + 1);
+
+ // Skip over any whitespace.
+ Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
+
+ // Find the entire completion string.
+ StringRef::size_type EOL = Buffer.find_first_of("\n\r");
+ if (EOL == StringRef::npos)
+ continue;
+
+ StringRef Line = Buffer.substr(0, EOL);
+ Buffer = Buffer.substr(EOL + 1);
+ CodeCompletionString *CCStr = CodeCompletionString::Deserialize(Line);
+ if (!CCStr || CCStr->empty())
+ continue;
+
+ // Vend the code-completion result to the caller.
+ CXCompletionResult Result;
+ Result.CursorKind = parseResultKind(Kind);
+ Result.CompletionString = CCStr;
+ if (completion_iterator)
+ completion_iterator(&Result, client_data);
+ delete CCStr;
+ } while (true);
+ delete F;
+ }
+
+ ResultsFile.eraseFromDisk();
+}
+
} // end extern "C"
diff --git a/tools/CIndex/CIndex.exports b/tools/CIndex/CIndex.exports
index 5f461d8..2892ce50e 100644
--- a/tools/CIndex/CIndex.exports
+++ b/tools/CIndex/CIndex.exports
@@ -1,8 +1,14 @@
+_clang_codeComplete
_clang_createIndex
_clang_createTranslationUnit
_clang_createTranslationUnitFromSourceFile
_clang_disposeIndex
+_clang_disposeString
_clang_disposeTranslationUnit
+_clang_equalCursors
+_clang_getCompletionChunkCompletionString
+_clang_getCompletionChunkKind
+_clang_getCompletionChunkText
_clang_getCursor
_clang_getCursorColumn
_clang_getCursorDecl
@@ -13,6 +19,7 @@ _clang_getCursorLine
_clang_getCursorSource
_clang_getCursorSourceFile
_clang_getCursorSpelling
+_clang_getCString
_clang_getDeclColumn
_clang_getDeclLine
_clang_getDeclSource
@@ -24,6 +31,8 @@ _clang_getEntity
_clang_getEntityFromDecl
_clang_getFileName
_clang_getFileTime
+_clang_getNullCursor
+_clang_getNumCompletionChunks
_clang_getTranslationUnitSpelling
_clang_getURI
_clang_isDeclaration
diff --git a/tools/CIndex/CMakeLists.txt b/tools/CIndex/CMakeLists.txt
index dd0eeea..69de8a1 100644
--- a/tools/CIndex/CMakeLists.txt
+++ b/tools/CIndex/CMakeLists.txt
@@ -3,7 +3,7 @@ set(SHARED_LIBRARY TRUE)
set(LLVM_NO_RTTI 1)
set(LLVM_USED_LIBS
- clangFrontend clangIndex clangSema clangAST clangLex clangBasic)
+ clangFrontend clangIndex clangSema clangAnalysis clangAST clangParse clangLex clangBasic)
set( LLVM_LINK_COMPONENTS
MC
diff --git a/tools/CIndex/Makefile b/tools/CIndex/Makefile
index a9ff394..a34f68b 100644
--- a/tools/CIndex/Makefile
+++ b/tools/CIndex/Makefile
@@ -22,7 +22,7 @@ LINK_LIBS_IN_SHARED = 1
SHARED_LIBRARY = 1
LINK_COMPONENTS := MC support
-USEDLIBS = clangFrontend.a clangIndex.a clangSema.a clangAST.a clangLex.a clangBasic.a
+USEDLIBS = clangFrontend.a clangIndex.a clangSema.a clangAnalysis.a clangAST.a clangParse.a clangLex.a clangBasic.a
include $(LEVEL)/Makefile.common
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 222512a..8cded43 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -1,9 +1,5 @@
add_subdirectory(clang-cc)
add_subdirectory(driver)
add_subdirectory(index-test)
-option(CLANG_BUILD_EXPERIMENTAL "Build experimenal Clang tools" OFF)
-if (CLANG_BUILD_EXPERIMENTAL)
- add_subdirectory(wpa)
-endif ()
add_subdirectory(CIndex)
add_subdirectory(c-index-test)
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index 8791ee2..289dee9 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -1,9 +1,14 @@
/* c-index-test.c */
#include "clang-c/Index.h"
+#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+/******************************************************************************/
+/* Utility functions. */
+/******************************************************************************/
+
#ifdef _MSC_VER
char *basename(const char* path)
{
@@ -22,13 +27,32 @@ char *basename(const char* path)
extern char *basename(const char *);
#endif
+static unsigned CreateTranslationUnit(CXIndex Idx, const char *file,
+ CXTranslationUnit *TU) {
+
+ *TU = clang_createTranslationUnit(Idx, file);
+ if (!TU) {
+ fprintf(stderr, "Unable to load translation unit from '%s'!\n", file);
+ return 0;
+ }
+ return 1;
+}
+
+
+/******************************************************************************/
+/* Pretty-printing. */
+/******************************************************************************/
+
static void PrintCursor(CXCursor Cursor) {
if (clang_isInvalid(Cursor.kind))
- printf("Invalid Cursor => %s\n", clang_getCursorKindSpelling(Cursor.kind));
+ printf("Invalid Cursor => %s", clang_getCursorKindSpelling(Cursor.kind));
else {
CXDecl DeclReferenced;
+ CXString string;
+ string = clang_getCursorSpelling(Cursor);
printf("%s=%s", clang_getCursorKindSpelling(Cursor.kind),
- clang_getCursorSpelling(Cursor));
+ clang_getCString(string));
+ clang_disposeString(string);
DeclReferenced = clang_getCursorDecl(Cursor);
if (DeclReferenced)
printf(":%d:%d", clang_getDeclLine(DeclReferenced),
@@ -36,25 +60,43 @@ static void PrintCursor(CXCursor Cursor) {
}
}
+static const char* GetCursorSource(CXCursor Cursor) {
+ const char *source = clang_getCursorSource(Cursor);
+ if (!source)
+ return "<invalid loc>";
+ return basename(source);
+}
+
+/******************************************************************************/
+/* Logic for testing clang_loadTranslationUnit(). */
+/******************************************************************************/
+
static void DeclVisitor(CXDecl Dcl, CXCursor Cursor, CXClientData Filter)
{
if (!Filter || (Cursor.kind == *(enum CXCursorKind *)Filter)) {
- printf("// CHECK: %s:%d:%d: ", basename(clang_getCursorSource(Cursor)),
+ CXString string;
+ printf("// CHECK: %s:%d:%d: ", GetCursorSource(Cursor),
clang_getCursorLine(Cursor),
clang_getCursorColumn(Cursor));
PrintCursor(Cursor);
- printf(" [Context=%s]\n", clang_getDeclSpelling(Dcl));
+ string = clang_getDeclSpelling(Dcl);
+ printf(" [Context=%s]\n", clang_getCString(string));
+ clang_disposeString(string);
}
}
static void TranslationUnitVisitor(CXTranslationUnit Unit, CXCursor Cursor,
CXClientData Filter)
{
if (!Filter || (Cursor.kind == *(enum CXCursorKind *)Filter)) {
- printf("// CHECK: %s:%d:%d: ", basename(clang_getCursorSource(Cursor)),
+ CXString string;
+ printf("// CHECK: %s:%d:%d: ", GetCursorSource(Cursor),
clang_getCursorLine(Cursor),
clang_getCursorColumn(Cursor));
PrintCursor(Cursor);
- printf(" [Context=%s]\n", basename(clang_getTranslationUnitSpelling(Unit)));
+ string = clang_getTranslationUnitSpelling(Unit);
+ printf(" [Context=%s]\n",
+ basename(clang_getCString(string)));
+ clang_disposeString(string);
clang_loadDeclaration(Cursor.decl, DeclVisitor, 0);
@@ -82,10 +124,13 @@ static void TranslationUnitVisitor(CXTranslationUnit Unit, CXCursor Cursor,
if (Ref.kind == CXCursor_NoDeclFound) {
/* Nothing found here; that's fine. */
} else if (Ref.kind != CXCursor_FunctionDecl) {
- printf("// CHECK: %s:%d:%d: ", basename(clang_getCursorSource(Ref)),
- curLine, curColumn);
+ CXString string;
+ printf("// CHECK: %s:%d:%d: ", GetCursorSource(Ref),
+ curLine, curColumn);
PrintCursor(Ref);
- printf(" [Context:%s]\n", clang_getDeclSpelling(Ref.decl));
+ string = clang_getDeclSpelling(Ref.decl);
+ printf(" [Context:%s]\n", clang_getCString(string));
+ clang_disposeString(string);
}
startBuf++;
}
@@ -94,43 +139,280 @@ static void TranslationUnitVisitor(CXTranslationUnit Unit, CXCursor Cursor,
}
}
-/*
- * First sign of life:-)
- */
-int main(int argc, char **argv) {
- if (argc != 3) {
- printf("Incorrect usage of c-index-test (requires 3 arguments)\n");
- return 0;
- }
- {
+int perform_test_load_tu(const char *file, const char *filter) {
CXIndex Idx;
CXTranslationUnit TU;
enum CXCursorKind K = CXCursor_NotImplemented;
-
- Idx = clang_createIndex(/* excludeDeclsFromPCH */ !strcmp(argv[2], "local") ? 1 : 0,
+ enum CXCursorKind *ck = &K;
+ Idx = clang_createIndex(/* excludeDeclsFromPCH */
+ !strcmp(filter, "local") ? 1 : 0,
/* displayDiagnostics */ 1);
- TU = clang_createTranslationUnit(Idx, argv[1]);
+ if (!CreateTranslationUnit(Idx, file, &TU))
+ return 1;
+
+ /* Perform some simple filtering. */
+ if (!strcmp(filter, "all") || !strcmp(filter, "local")) ck = NULL;
+ else if (!strcmp(filter, "category")) K = CXCursor_ObjCCategoryDecl;
+ else if (!strcmp(filter, "interface")) K = CXCursor_ObjCInterfaceDecl;
+ else if (!strcmp(filter, "protocol")) K = CXCursor_ObjCProtocolDecl;
+ else if (!strcmp(filter, "function")) K = CXCursor_FunctionDecl;
+ else if (!strcmp(filter, "typedef")) K = CXCursor_TypedefDecl;
+ else {
+ fprintf(stderr, "Unknown filter for -test-load-tu: %s\n", filter);
+ return 1;
+ }
+
+ clang_loadTranslationUnit(TU, TranslationUnitVisitor, ck);
+ clang_disposeTranslationUnit(TU);
+ return 0;
+}
- if (!TU) {
- fprintf(stderr, "Unable to load translation unit!\n");
+/******************************************************************************/
+/* Logic for testing clang_getCursor(). */
+/******************************************************************************/
+
+static void print_cursor_file_scan(CXCursor cursor,
+ unsigned start_line, unsigned start_col,
+ unsigned end_line, unsigned end_col,
+ const char *prefix) {
+ printf("// CHECK");
+ if (prefix)
+ printf("-%s", prefix);
+ printf("{start_line=%d start_col=%d end_line=%d end_col=%d} ",
+ start_line, start_col, end_line, end_col);
+ PrintCursor(cursor);
+ printf("\n");
+}
+
+static int perform_file_scan(const char *ast_file, const char *source_file,
+ const char *prefix) {
+ CXIndex Idx;
+ CXTranslationUnit TU;
+ FILE *fp;
+ unsigned line;
+ CXCursor prevCursor;
+ unsigned printed;
+ unsigned start_line, start_col, last_line, last_col;
+ size_t i;
+
+ if (!(Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1,
+ /* displayDiagnostics */ 1))) {
+ fprintf(stderr, "Could not create Index\n");
+ return 1;
+ }
+
+ if (!CreateTranslationUnit(Idx, ast_file, &TU))
+ return 1;
+
+ if ((fp = fopen(source_file, "r")) == NULL) {
+ fprintf(stderr, "Could not open '%s'\n", source_file);
+ return 1;
+ }
+
+ line = 0;
+ prevCursor = clang_getNullCursor();
+ printed = 0;
+ start_line = last_line = 1;
+ start_col = last_col = 1;
+
+ while (!feof(fp)) {
+ size_t len = 0;
+ int c;
+
+ while ((c = fgetc(fp)) != EOF) {
+ len++;
+ if (c == '\n')
+ break;
+ }
+
+ ++line;
+
+ for (i = 0; i < len ; ++i) {
+ CXCursor cursor;
+ cursor = clang_getCursor(TU, source_file, line, i+1);
+
+ if (!clang_equalCursors(cursor, prevCursor) &&
+ prevCursor.kind != CXCursor_InvalidFile) {
+ print_cursor_file_scan(prevCursor, start_line, start_col,
+ last_line, last_col, prefix);
+ printed = 1;
+ start_line = line;
+ start_col = (unsigned) i+1;
+ }
+ else {
+ printed = 0;
+ }
+
+ prevCursor = cursor;
+ last_line = line;
+ last_col = (unsigned) i+1;
+ }
+ }
+
+ if (!printed && prevCursor.kind != CXCursor_InvalidFile) {
+ print_cursor_file_scan(prevCursor, start_line, start_col,
+ last_line, last_col, prefix);
+ }
+
+ fclose(fp);
+ return 0;
+}
+
+/******************************************************************************/
+/* Logic for testing clang_codeComplete(). */
+/******************************************************************************/
+
+/* Parse file:line:column from the input string. Returns 0 on success, non-zero
+ on failure. If successful, the pointer *filename will contain newly-allocated
+ memory (that will be owned by the caller) to store the file name. */
+int parse_file_line_column(const char *input, char **filename, unsigned *line,
+ unsigned *column) {
+ /* Find the second colon. */
+ const char *second_colon = strrchr(input, ':'), *first_colon;
+ char *endptr = 0;
+ if (!second_colon || second_colon == input) {
+ fprintf(stderr, "could not parse filename:line:column in '%s'\n", input);
return 1;
}
- if (!strcmp(argv[2], "all") || !strcmp(argv[2], "local")) {
- clang_loadTranslationUnit(TU, TranslationUnitVisitor, 0);
- clang_disposeTranslationUnit(TU);
+ /* Parse the column number. */
+ *column = strtol(second_colon + 1, &endptr, 10);
+ if (*endptr != 0) {
+ fprintf(stderr, "could not parse column in '%s'\n", input);
return 1;
}
- /* Perform some simple filtering. */
- if (!strcmp(argv[2], "category")) K = CXCursor_ObjCCategoryDecl;
- else if (!strcmp(argv[2], "interface")) K = CXCursor_ObjCInterfaceDecl;
- else if (!strcmp(argv[2], "protocol")) K = CXCursor_ObjCProtocolDecl;
- else if (!strcmp(argv[2], "function")) K = CXCursor_FunctionDecl;
- else if (!strcmp(argv[2], "typedef")) K = CXCursor_TypedefDecl;
- clang_loadTranslationUnit(TU, TranslationUnitVisitor, &K);
- clang_disposeTranslationUnit(TU);
- return 1;
+ /* Find the first colon. */
+ first_colon = second_colon - 1;
+ while (first_colon != input && *first_colon != ':')
+ --first_colon;
+ if (first_colon == input) {
+ fprintf(stderr, "could not parse line in '%s'\n", input);
+ return 1;
+ }
+
+ /* Parse the line number. */
+ *line = strtol(first_colon + 1, &endptr, 10);
+ if (*endptr != ':') {
+ fprintf(stderr, "could not parse line in '%s'\n", input);
+ return 1;
+ }
+
+ /* Copy the file name. */
+ *filename = (char*)malloc(first_colon - input + 1);
+ memcpy(*filename, input, first_colon - input);
+ (*filename)[first_colon - input] = 0;
+ return 0;
+}
+
+const char *
+clang_getCompletionChunkKindSpelling(enum CXCompletionChunkKind Kind) {
+ switch (Kind) {
+ case CXCompletionChunk_Optional: return "Optional";
+ case CXCompletionChunk_TypedText: return "TypedText";
+ case CXCompletionChunk_Text: return "Text";
+ case CXCompletionChunk_Placeholder: return "Placeholder";
+ case CXCompletionChunk_Informative: return "Informative";
+ case CXCompletionChunk_CurrentParameter: return "CurrentParameter";
+ case CXCompletionChunk_LeftParen: return "LeftParen";
+ case CXCompletionChunk_RightParen: return "RightParen";
+ case CXCompletionChunk_LeftBracket: return "LeftBracket";
+ case CXCompletionChunk_RightBracket: return "RightBracket";
+ case CXCompletionChunk_LeftBrace: return "LeftBrace";
+ case CXCompletionChunk_RightBrace: return "RightBrace";
+ case CXCompletionChunk_LeftAngle: return "LeftAngle";
+ case CXCompletionChunk_RightAngle: return "RightAngle";
+ case CXCompletionChunk_Comma: return "Comma";
}
+
+ return "Unknown";
+}
+
+void print_completion_string(CXCompletionString completion_string, FILE *file) {
+ int I, N;
+
+ N = clang_getNumCompletionChunks(completion_string);
+ for (I = 0; I != N; ++I) {
+ const char *text = 0;
+ enum CXCompletionChunkKind Kind
+ = clang_getCompletionChunkKind(completion_string, I);
+
+ if (Kind == CXCompletionChunk_Optional) {
+ fprintf(file, "{Optional ");
+ print_completion_string(
+ clang_getCompletionChunkCompletionString(completion_string, I),
+ file);
+ fprintf(file, "}");
+ continue;
+ }
+
+ text = clang_getCompletionChunkText(completion_string, I);
+ fprintf(file, "{%s %s}",
+ clang_getCompletionChunkKindSpelling(Kind),
+ text? text : "");
+ }
+}
+
+void print_completion_result(CXCompletionResult *completion_result,
+ CXClientData client_data) {
+ FILE *file = (FILE *)client_data;
+ fprintf(file, "%s:",
+ clang_getCursorKindSpelling(completion_result->CursorKind));
+ print_completion_string(completion_result->CompletionString, file);
+ fprintf(file, "\n");
+}
+
+int perform_code_completion(int argc, const char **argv) {
+ const char *input = argv[1];
+ char *filename = 0;
+ unsigned line;
+ unsigned column;
+ CXIndex CIdx;
+ int errorCode;
+
+ input += strlen("-code-completion-at=");
+ if ((errorCode = parse_file_line_column(input, &filename, &line, &column)))
+ return errorCode;
+
+ CIdx = clang_createIndex(0, 0);
+ clang_codeComplete(CIdx, argv[argc - 1], argc - 3, argv + 2,
+ filename, line, column, &print_completion_result, stdout);
+ clang_disposeIndex(CIdx);
+ free(filename);
+
+ return 0;
+}
+
+/******************************************************************************/
+/* Command line processing. */
+/******************************************************************************/
+
+static void print_usage(void) {
+ fprintf(stderr,
+ "usage: c-index-test -code-completion-at=<site> <compiler arguments>\n"
+ " c-index-test -test-file-scan <AST file> <source file> "
+ "[FileCheck prefix]\n"
+ " c-index-test -test-load-tu <AST file> <symbol filter>\n\n"
+ " <symbol filter> options for -test-load-tu:\n%s",
+ " all - load all symbols, including those from PCH\n"
+ " local - load all symbols except those in PCH\n"
+ " category - only load ObjC categories (non-PCH)\n"
+ " interface - only load ObjC interfaces (non-PCH)\n"
+ " protocol - only load ObjC protocols (non-PCH)\n"
+ " function - only load functions (non-PCH)\n"
+ " typedef - only load typdefs (non-PCH)\n\n");
+}
+
+int main(int argc, const char **argv) {
+ if (argc > 2 && strstr(argv[1], "-code-completion-at=") == argv[1])
+ return perform_code_completion(argc, argv);
+ if (argc == 4 && strcmp(argv[1], "-test-load-tu") == 0)
+ return perform_test_load_tu(argv[2], argv[3]);
+ if (argc >= 4 && strcmp(argv[1], "-test-file-scan") == 0)
+ return perform_file_scan(argv[2], argv[3],
+ argc >= 5 ? argv[4] : 0);
+
+ print_usage();
+ return 1;
}
diff --git a/tools/clang-cc/CMakeLists.txt b/tools/clang-cc/CMakeLists.txt
index 85e4c7c..e7da908 100644
--- a/tools/clang-cc/CMakeLists.txt
+++ b/tools/clang-cc/CMakeLists.txt
@@ -23,6 +23,7 @@ set( LLVM_LINK_COMPONENTS
add_clang_executable(clang-cc
clang-cc.cpp
+ Options.cpp
)
add_dependencies(clang-cc clang-headers)
diff --git a/tools/clang-cc/Options.cpp b/tools/clang-cc/Options.cpp
new file mode 100644
index 0000000..b5190eb
--- /dev/null
+++ b/tools/clang-cc/Options.cpp
@@ -0,0 +1,1330 @@
+//===--- Options.cpp - clang-cc Option Handling ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// This file contains "pure" option handling, it is only responsible for turning
+// the options into internal *Option classes, but shouldn't have any other
+// logic.
+
+#include "Options.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Frontend/AnalysisConsumer.h"
+#include "clang/CodeGen/CodeGenOptions.h"
+#include "clang/Frontend/DependencyOutputOptions.h"
+#include "clang/Frontend/DiagnosticOptions.h"
+#include "clang/Frontend/FrontendOptions.h"
+#include "clang/Frontend/HeaderSearchOptions.h"
+#include "clang/Frontend/PCHReader.h"
+#include "clang/Frontend/PreprocessorOptions.h"
+#include "clang/Frontend/PreprocessorOutputOptions.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/RegistryParser.h"
+#include "llvm/System/Host.h"
+#include <stdio.h>
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Analyzer Options
+//===----------------------------------------------------------------------===//
+
+namespace analyzeroptions {
+
+static llvm::cl::list<Analyses>
+AnalysisList(llvm::cl::desc("Source Code Analysis - Checks and Analyses"),
+llvm::cl::values(
+#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)\
+clEnumValN(NAME, CMDFLAG, DESC),
+#include "clang/Frontend/Analyses.def"
+clEnumValEnd));
+
+static llvm::cl::opt<AnalysisStores>
+AnalysisStoreOpt("analyzer-store",
+ llvm::cl::desc("Source Code Analysis - Abstract Memory Store Models"),
+ llvm::cl::init(BasicStoreModel),
+ llvm::cl::values(
+#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN)\
+clEnumValN(NAME##Model, CMDFLAG, DESC),
+#include "clang/Frontend/Analyses.def"
+clEnumValEnd));
+
+static llvm::cl::opt<AnalysisConstraints>
+AnalysisConstraintsOpt("analyzer-constraints",
+ llvm::cl::desc("Source Code Analysis - Symbolic Constraint Engines"),
+ llvm::cl::init(RangeConstraintsModel),
+ llvm::cl::values(
+#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN)\
+clEnumValN(NAME##Model, CMDFLAG, DESC),
+#include "clang/Frontend/Analyses.def"
+clEnumValEnd));
+
+static llvm::cl::opt<AnalysisDiagClients>
+AnalysisDiagOpt("analyzer-output",
+ llvm::cl::desc("Source Code Analysis - Output Options"),
+ llvm::cl::init(PD_HTML),
+ llvm::cl::values(
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREATE)\
+clEnumValN(PD_##NAME, CMDFLAG, DESC),
+#include "clang/Frontend/Analyses.def"
+clEnumValEnd));
+
+static llvm::cl::opt<bool>
+AnalyzeAll("analyzer-opt-analyze-headers",
+ llvm::cl::desc("Force the static analyzer to analyze "
+ "functions defined in header files"));
+
+static llvm::cl::opt<bool>
+AnalyzerDisplayProgress("analyzer-display-progress",
+ llvm::cl::desc("Emit verbose output about the analyzer's progress"));
+
+static llvm::cl::opt<bool>
+AnalyzerExperimentalChecks("analyzer-experimental-checks",
+ llvm::cl::desc("Use experimental path-sensitive checks"));
+
+static llvm::cl::opt<bool>
+AnalyzerExperimentalInternalChecks("analyzer-experimental-internal-checks",
+ llvm::cl::desc("Use new default path-sensitive checks currently in testing"));
+
+static llvm::cl::opt<std::string>
+AnalyzeSpecificFunction("analyze-function",
+ llvm::cl::desc("Run analysis on specific function"));
+
+static llvm::cl::opt<bool>
+EagerlyAssume("analyzer-eagerly-assume",
+ llvm::cl::init(false),
+ llvm::cl::desc("Eagerly assume the truth/falseness of some "
+ "symbolic constraints"));
+
+static llvm::cl::opt<bool>
+PurgeDead("analyzer-purge-dead",
+ llvm::cl::init(true),
+ llvm::cl::desc("Remove dead symbols, bindings, and constraints before"
+ " processing a statement"));
+
+static llvm::cl::opt<bool>
+TrimGraph("trim-egraph",
+ llvm::cl::desc("Only show error-related paths in the analysis graph"));
+
+static llvm::cl::opt<bool>
+VisualizeEGDot("analyzer-viz-egraph-graphviz",
+ llvm::cl::desc("Display exploded graph using GraphViz"));
+
+static llvm::cl::opt<bool>
+VisualizeEGUbi("analyzer-viz-egraph-ubigraph",
+ llvm::cl::desc("Display exploded graph using Ubigraph"));
+
+}
+
+//===----------------------------------------------------------------------===//
+// Code Generation Options
+//===----------------------------------------------------------------------===//
+
+namespace codegenoptions {
+
+static llvm::cl::opt<bool>
+DisableLLVMOptimizations("disable-llvm-optzns",
+ llvm::cl::desc("Don't run LLVM optimization passes"));
+
+static llvm::cl::opt<bool>
+DisableRedZone("disable-red-zone",
+ llvm::cl::desc("Do not emit code that uses the red zone."),
+ llvm::cl::init(false));
+
+static llvm::cl::opt<bool>
+GenerateDebugInfo("g",
+ llvm::cl::desc("Generate source level debug information"));
+
+static llvm::cl::opt<bool>
+NoCommon("fno-common",
+ llvm::cl::desc("Compile common globals like normal definitions"),
+ llvm::cl::ValueDisallowed);
+
+static llvm::cl::opt<bool>
+NoImplicitFloat("no-implicit-float",
+ llvm::cl::desc("Don't generate implicit floating point instructions (x86-only)"),
+ llvm::cl::init(false));
+
+static llvm::cl::opt<bool>
+NoMergeConstants("fno-merge-all-constants",
+ llvm::cl::desc("Disallow merging of constants."));
+
+// It might be nice to add bounds to the CommandLine library directly.
+struct OptLevelParser : public llvm::cl::parser<unsigned> {
+ bool parse(llvm::cl::Option &O, llvm::StringRef ArgName,
+ llvm::StringRef Arg, unsigned &Val) {
+ if (llvm::cl::parser<unsigned>::parse(O, ArgName, Arg, Val))
+ return true;
+ if (Val > 3)
+ return O.error("'" + Arg + "' invalid optimization level!");
+ return false;
+ }
+};
+static llvm::cl::opt<unsigned, false, OptLevelParser>
+OptLevel("O", llvm::cl::Prefix,
+ llvm::cl::desc("Optimization level"),
+ llvm::cl::init(0));
+
+static llvm::cl::opt<bool>
+OptSize("Os", llvm::cl::desc("Optimize for size"));
+
+}
+
+//===----------------------------------------------------------------------===//
+// Dependency Output Options
+//===----------------------------------------------------------------------===//
+
+namespace dependencyoutputoptions {
+
+static llvm::cl::opt<std::string>
+DependencyFile("dependency-file",
+ llvm::cl::desc("Filename (or -) to write dependency output to"));
+
+static llvm::cl::opt<bool>
+DependenciesIncludeSystemHeaders("sys-header-deps",
+ llvm::cl::desc("Include system headers in dependency output"));
+
+static llvm::cl::list<std::string>
+DependencyTargets("MT",
+ llvm::cl::desc("Specify target for dependency"));
+
+static llvm::cl::opt<bool>
+PhonyDependencyTarget("MP",
+ llvm::cl::desc("Create phony target for each dependency "
+ "(other than main file)"));
+
+}
+
+//===----------------------------------------------------------------------===//
+// Diagnostic Options
+//===----------------------------------------------------------------------===//
+
+namespace diagnosticoptions {
+
+static llvm::cl::opt<std::string>
+DumpBuildInformation("dump-build-information",
+ llvm::cl::value_desc("filename"),
+ llvm::cl::desc("output a dump of some build information to a file"));
+
+static llvm::cl::opt<bool>
+NoShowColumn("fno-show-column",
+ llvm::cl::desc("Do not include column number on diagnostics"));
+
+static llvm::cl::opt<bool>
+NoShowLocation("fno-show-source-location",
+ llvm::cl::desc("Do not include source location information with"
+ " diagnostics"));
+
+static llvm::cl::opt<bool>
+NoCaretDiagnostics("fno-caret-diagnostics",
+ llvm::cl::desc("Do not include source line and caret with"
+ " diagnostics"));
+
+static llvm::cl::opt<bool>
+NoDiagnosticsFixIt("fno-diagnostics-fixit-info",
+ llvm::cl::desc("Do not include fixit information in"
+ " diagnostics"));
+
+static llvm::cl::opt<bool> OptNoWarnings("w");
+
+static llvm::cl::opt<bool> OptPedantic("pedantic");
+
+static llvm::cl::opt<bool> OptPedanticErrors("pedantic-errors");
+
+// This gets all -W options, including -Werror, -W[no-]system-headers, etc. The
+// driver has stripped off -Wa,foo etc. The driver has also translated -W to
+// -Wextra, so we don't need to worry about it.
+static llvm::cl::list<std::string>
+OptWarnings("W", llvm::cl::Prefix, llvm::cl::ValueOptional);
+
+static llvm::cl::opt<bool>
+PrintSourceRangeInfo("fdiagnostics-print-source-range-info",
+ llvm::cl::desc("Print source range spans in numeric form"));
+
+static llvm::cl::opt<bool>
+PrintDiagnosticOption("fdiagnostics-show-option",
+ llvm::cl::desc("Print diagnostic name with mappable diagnostics"));
+
+static llvm::cl::opt<unsigned>
+MessageLength("fmessage-length",
+ llvm::cl::desc("Format message diagnostics so that they fit "
+ "within N columns or fewer, when possible."),
+ llvm::cl::value_desc("N"));
+
+static llvm::cl::opt<bool>
+PrintColorDiagnostic("fcolor-diagnostics",
+ llvm::cl::desc("Use colors in diagnostics"));
+
+static llvm::cl::opt<bool>
+SilenceRewriteMacroWarning("Wno-rewrite-macros", llvm::cl::init(false),
+ llvm::cl::desc("Silence ObjC rewriting warnings"));
+
+static llvm::cl::opt<bool>
+VerifyDiagnostics("verify",
+ llvm::cl::desc("Verify emitted diagnostics and warnings"));
+
+}
+
+//===----------------------------------------------------------------------===//
+// Frontend Options
+//===----------------------------------------------------------------------===//
+
+namespace frontendoptions {
+
+using namespace clang::frontend;
+
+static llvm::cl::opt<ParsedSourceLocation>
+CodeCompletionAt("code-completion-at",
+ llvm::cl::value_desc("file:line:column"),
+ llvm::cl::desc("Dump code-completion information at a location"));
+
+static llvm::cl::opt<bool>
+CodeCompletionDebugPrinter("code-completion-debug-printer",
+ llvm::cl::desc("Use the \"debug\" code-completion print"),
+ llvm::cl::init(true));
+
+static llvm::cl::opt<bool>
+CodeCompletionWantsMacros("code-completion-macros",
+ llvm::cl::desc("Include macros in code-completion results"));
+
+static llvm::cl::opt<bool>
+DisableFree("disable-free",
+ llvm::cl::desc("Disable freeing of memory on exit"),
+ llvm::cl::init(false));
+
+static llvm::cl::opt<bool>
+EmptyInputOnly("empty-input-only",
+ llvm::cl::desc("Force running on an empty input file"));
+
+static llvm::cl::opt<FrontendOptions::InputKind>
+InputType("x", llvm::cl::desc("Input language type"),
+ llvm::cl::init(FrontendOptions::IK_None),
+ llvm::cl::values(clEnumValN(FrontendOptions::IK_C, "c", "C"),
+ clEnumValN(FrontendOptions::IK_OpenCL, "cl", "OpenCL C"),
+ clEnumValN(FrontendOptions::IK_CXX, "c++", "C++"),
+ clEnumValN(FrontendOptions::IK_ObjC, "objective-c",
+ "Objective C"),
+ clEnumValN(FrontendOptions::IK_ObjCXX, "objective-c++",
+ "Objective C++"),
+ clEnumValN(FrontendOptions::IK_PreprocessedC,
+ "cpp-output",
+ "Preprocessed C"),
+ clEnumValN(FrontendOptions::IK_Asm,
+ "assembler-with-cpp",
+ "Assembly Source Codde"),
+ clEnumValN(FrontendOptions::IK_PreprocessedCXX,
+ "c++-cpp-output",
+ "Preprocessed C++"),
+ clEnumValN(FrontendOptions::IK_PreprocessedObjC,
+ "objective-c-cpp-output",
+ "Preprocessed Objective C"),
+ clEnumValN(FrontendOptions::IK_PreprocessedObjCXX,
+ "objective-c++-cpp-output",
+ "Preprocessed Objective C++"),
+ clEnumValN(FrontendOptions::IK_C, "c-header",
+ "C header"),
+ clEnumValN(FrontendOptions::IK_ObjC, "objective-c-header",
+ "Objective-C header"),
+ clEnumValN(FrontendOptions::IK_CXX, "c++-header",
+ "C++ header"),
+ clEnumValN(FrontendOptions::IK_ObjCXX,
+ "objective-c++-header",
+ "Objective-C++ header"),
+ clEnumValN(FrontendOptions::IK_AST, "ast",
+ "Clang AST"),
+ clEnumValEnd));
+
+static llvm::cl::list<std::string>
+InputFilenames(llvm::cl::Positional, llvm::cl::desc("<input files>"));
+
+static llvm::cl::opt<std::string>
+InheritanceViewCls("cxx-inheritance-view",
+ llvm::cl::value_desc("class name"),
+ llvm::cl::desc("View C++ inheritance for a specified class"));
+
+static llvm::cl::list<ParsedSourceLocation>
+FixItAtLocations("fixit-at", llvm::cl::value_desc("source-location"),
+ llvm::cl::desc("Perform Fix-It modifications at the given source location"));
+
+static llvm::cl::opt<std::string>
+OutputFile("o",
+ llvm::cl::value_desc("path"),
+ llvm::cl::desc("Specify output file"));
+
+static llvm::cl::opt<std::string>
+PluginActionName("plugin",
+ llvm::cl::desc("Use the named plugin action "
+ "(use \"help\" to list available options)"));
+
+static llvm::cl::opt<ActionKind>
+ProgAction(llvm::cl::desc("Choose output type:"), llvm::cl::ZeroOrMore,
+ llvm::cl::init(ParseSyntaxOnly),
+ llvm::cl::values(
+ clEnumValN(RunPreprocessorOnly, "Eonly",
+ "Just run preprocessor, no output (for timings)"),
+ clEnumValN(PrintPreprocessedInput, "E",
+ "Run preprocessor, emit preprocessed file"),
+ clEnumValN(DumpRawTokens, "dump-raw-tokens",
+ "Lex file in raw mode and dump raw tokens"),
+ clEnumValN(RunAnalysis, "analyze",
+ "Run static analysis engine"),
+ clEnumValN(DumpTokens, "dump-tokens",
+ "Run preprocessor, dump internal rep of tokens"),
+ clEnumValN(ParseNoop, "parse-noop",
+ "Run parser with noop callbacks (for timings)"),
+ clEnumValN(ParseSyntaxOnly, "fsyntax-only",
+ "Run parser and perform semantic analysis"),
+ clEnumValN(FixIt, "fixit",
+ "Apply fix-it advice to the input source"),
+ clEnumValN(ParsePrintCallbacks, "parse-print-callbacks",
+ "Run parser and print each callback invoked"),
+ clEnumValN(EmitHTML, "emit-html",
+ "Output input source as HTML"),
+ clEnumValN(ASTPrint, "ast-print",
+ "Build ASTs and then pretty-print them"),
+ clEnumValN(ASTPrintXML, "ast-print-xml",
+ "Build ASTs and then print them in XML format"),
+ clEnumValN(ASTDump, "ast-dump",
+ "Build ASTs and then debug dump them"),
+ clEnumValN(ASTView, "ast-view",
+ "Build ASTs and view them with GraphViz"),
+ clEnumValN(PrintDeclContext, "print-decl-contexts",
+ "Print DeclContexts and their Decls"),
+ clEnumValN(DumpRecordLayouts, "dump-record-layouts",
+ "Dump record layout information"),
+ clEnumValN(GeneratePTH, "emit-pth",
+ "Generate pre-tokenized header file"),
+ clEnumValN(GeneratePCH, "emit-pch",
+ "Generate pre-compiled header file"),
+ clEnumValN(EmitAssembly, "S",
+ "Emit native assembly code"),
+ clEnumValN(EmitLLVM, "emit-llvm",
+ "Build ASTs then convert to LLVM, emit .ll file"),
+ clEnumValN(EmitBC, "emit-llvm-bc",
+ "Build ASTs then convert to LLVM, emit .bc file"),
+ clEnumValN(EmitLLVMOnly, "emit-llvm-only",
+ "Build ASTs and convert to LLVM, discarding output"),
+ clEnumValN(RewriteTest, "rewrite-test",
+ "Rewriter playground"),
+ clEnumValN(RewriteObjC, "rewrite-objc",
+ "Rewrite ObjC into C (code rewriter example)"),
+ clEnumValN(RewriteMacros, "rewrite-macros",
+ "Expand macros without full preprocessing"),
+ clEnumValN(RewriteBlocks, "rewrite-blocks",
+ "Rewrite Blocks to C"),
+ clEnumValEnd));
+
+static llvm::cl::opt<bool>
+RelocatablePCH("relocatable-pch",
+ llvm::cl::desc("Whether to build a relocatable precompiled "
+ "header"));
+static llvm::cl::opt<bool>
+Stats("print-stats",
+ llvm::cl::desc("Print performance metrics and statistics"));
+
+static llvm::cl::opt<bool>
+TimeReport("ftime-report",
+ llvm::cl::desc("Print the amount of time each "
+ "phase of compilation takes"));
+
+}
+
+//===----------------------------------------------------------------------===//
+// Language Options
+//===----------------------------------------------------------------------===//
+
+namespace langoptions {
+
+static llvm::cl::opt<bool>
+AllowBuiltins("fbuiltin", llvm::cl::init(true),
+ llvm::cl::desc("Disable implicit builtin knowledge of functions"));
+
+static llvm::cl::opt<bool>
+AltiVec("faltivec", llvm::cl::desc("Enable AltiVec vector initializer syntax"),
+ llvm::cl::init(false));
+
+static llvm::cl::opt<bool>
+AccessControl("faccess-control",
+ llvm::cl::desc("Enable C++ access control"));
+
+static llvm::cl::opt<bool>
+CharIsSigned("fsigned-char",
+ llvm::cl::desc("Force char to be a signed/unsigned type"));
+
+static llvm::cl::opt<bool>
+DollarsInIdents("fdollars-in-identifiers",
+ llvm::cl::desc("Allow '$' in identifiers"));
+
+static llvm::cl::opt<bool>
+EmitAllDecls("femit-all-decls",
+ llvm::cl::desc("Emit all declarations, even if unused"));
+
+static llvm::cl::opt<bool>
+EnableBlocks("fblocks", llvm::cl::desc("enable the 'blocks' language feature"));
+
+static llvm::cl::opt<bool>
+EnableHeinousExtensions("fheinous-gnu-extensions",
+ llvm::cl::desc("enable GNU extensions that you really really shouldn't use"),
+ llvm::cl::ValueDisallowed, llvm::cl::Hidden);
+
+static llvm::cl::opt<bool>
+Exceptions("fexceptions",
+ llvm::cl::desc("Enable support for exception handling"));
+
+static llvm::cl::opt<bool>
+Freestanding("ffreestanding",
+ llvm::cl::desc("Assert that the compilation takes place in a "
+ "freestanding environment"));
+
+static llvm::cl::opt<bool>
+GNURuntime("fgnu-runtime",
+ llvm::cl::desc("Generate output compatible with the standard GNU "
+ "Objective-C runtime"));
+
+/// LangStds - Language standards we support.
+enum LangStds {
+ lang_unspecified,
+ lang_c89, lang_c94, lang_c99,
+ lang_gnu89, lang_gnu99,
+ lang_cxx98, lang_gnucxx98,
+ lang_cxx0x, lang_gnucxx0x
+};
+static llvm::cl::opt<LangStds>
+LangStd("std", llvm::cl::desc("Language standard to compile for"),
+ llvm::cl::init(lang_unspecified),
+ llvm::cl::values(clEnumValN(lang_c89, "c89", "ISO C 1990"),
+ clEnumValN(lang_c89, "c90", "ISO C 1990"),
+ clEnumValN(lang_c89, "iso9899:1990", "ISO C 1990"),
+ clEnumValN(lang_c94, "iso9899:199409",
+ "ISO C 1990 with amendment 1"),
+ clEnumValN(lang_c99, "c99", "ISO C 1999"),
+ clEnumValN(lang_c99, "c9x", "ISO C 1999"),
+ clEnumValN(lang_c99, "iso9899:1999", "ISO C 1999"),
+ clEnumValN(lang_c99, "iso9899:199x", "ISO C 1999"),
+ clEnumValN(lang_gnu89, "gnu89",
+ "ISO C 1990 with GNU extensions"),
+ clEnumValN(lang_gnu99, "gnu99",
+ "ISO C 1999 with GNU extensions (default for C)"),
+ clEnumValN(lang_gnu99, "gnu9x",
+ "ISO C 1999 with GNU extensions"),
+ clEnumValN(lang_cxx98, "c++98",
+ "ISO C++ 1998 with amendments"),
+ clEnumValN(lang_gnucxx98, "gnu++98",
+ "ISO C++ 1998 with amendments and GNU "
+ "extensions (default for C++)"),
+ clEnumValN(lang_cxx0x, "c++0x",
+ "Upcoming ISO C++ 200x with amendments"),
+ clEnumValN(lang_gnucxx0x, "gnu++0x",
+ "Upcoming ISO C++ 200x with amendments and GNU "
+ "extensions"),
+ clEnumValEnd));
+
+static llvm::cl::opt<bool>
+MSExtensions("fms-extensions",
+ llvm::cl::desc("Accept some non-standard constructs used in "
+ "Microsoft header files "));
+
+static llvm::cl::opt<std::string>
+MainFileName("main-file-name",
+ llvm::cl::desc("Main file name to use for debug info"));
+
+static llvm::cl::opt<bool>
+MathErrno("fmath-errno", llvm::cl::init(true),
+ llvm::cl::desc("Require math functions to respect errno"));
+
+static llvm::cl::opt<bool>
+NoElideConstructors("fno-elide-constructors",
+ llvm::cl::desc("Disable C++ copy constructor elision"));
+
+static llvm::cl::opt<bool>
+NoLaxVectorConversions("fno-lax-vector-conversions",
+ llvm::cl::desc("Disallow implicit conversions between "
+ "vectors with a different number of "
+ "elements or different element types"));
+
+
+static llvm::cl::opt<bool>
+NoOperatorNames("fno-operator-names",
+ llvm::cl::desc("Do not treat C++ operator name keywords as "
+ "synonyms for operators"));
+
+static llvm::cl::opt<std::string>
+ObjCConstantStringClass("fconstant-string-class",
+ llvm::cl::value_desc("class name"),
+ llvm::cl::desc("Specify the class to use for constant "
+ "Objective-C string objects."));
+
+static llvm::cl::opt<bool>
+ObjCEnableGC("fobjc-gc",
+ llvm::cl::desc("Enable Objective-C garbage collection"));
+
+static llvm::cl::opt<bool>
+ObjCExclusiveGC("fobjc-gc-only",
+ llvm::cl::desc("Use GC exclusively for Objective-C related "
+ "memory management"));
+
+static llvm::cl::opt<bool>
+ObjCEnableGCBitmapPrint("print-ivar-layout",
+ llvm::cl::desc("Enable Objective-C Ivar layout bitmap print trace"));
+
+static llvm::cl::opt<bool>
+ObjCNonFragileABI("fobjc-nonfragile-abi",
+ llvm::cl::desc("enable objective-c's nonfragile abi"));
+
+static llvm::cl::opt<bool>
+OverflowChecking("ftrapv",
+ llvm::cl::desc("Trap on integer overflow"),
+ llvm::cl::init(false));
+
+static llvm::cl::opt<unsigned>
+PICLevel("pic-level", llvm::cl::desc("Value for __PIC__"));
+
+static llvm::cl::opt<bool>
+PThread("pthread", llvm::cl::desc("Support POSIX threads in generated code"),
+ llvm::cl::init(false));
+
+static llvm::cl::opt<bool>
+PascalStrings("fpascal-strings",
+ llvm::cl::desc("Recognize and construct Pascal-style "
+ "string literals"));
+
+static llvm::cl::opt<bool>
+Rtti("frtti", llvm::cl::init(true),
+ llvm::cl::desc("Enable generation of rtti information"));
+
+static llvm::cl::opt<bool>
+ShortWChar("fshort-wchar",
+ llvm::cl::desc("Force wchar_t to be a short unsigned int"));
+
+static llvm::cl::opt<bool>
+StaticDefine("static-define", llvm::cl::desc("Should __STATIC__ be defined"));
+
+static llvm::cl::opt<int>
+StackProtector("stack-protector",
+ llvm::cl::desc("Enable stack protectors"),
+ llvm::cl::init(-1));
+
+static llvm::cl::opt<LangOptions::VisibilityMode>
+SymbolVisibility("fvisibility",
+ llvm::cl::desc("Set the default symbol visibility:"),
+ llvm::cl::init(LangOptions::Default),
+ llvm::cl::values(clEnumValN(LangOptions::Default, "default",
+ "Use default symbol visibility"),
+ clEnumValN(LangOptions::Hidden, "hidden",
+ "Use hidden symbol visibility"),
+ clEnumValN(LangOptions::Protected,"protected",
+ "Use protected symbol visibility"),
+ clEnumValEnd));
+
+static llvm::cl::opt<unsigned>
+TemplateDepth("ftemplate-depth", llvm::cl::init(99),
+ llvm::cl::desc("Maximum depth of recursive template "
+ "instantiation"));
+
+static llvm::cl::opt<bool>
+Trigraphs("trigraphs", llvm::cl::desc("Process trigraph sequences"));
+
+static llvm::cl::opt<bool>
+WritableStrings("fwritable-strings",
+ llvm::cl::desc("Store string literals as writable data"));
+
+}
+
+//===----------------------------------------------------------------------===//
+// General Preprocessor Options
+//===----------------------------------------------------------------------===//
+
+namespace preprocessoroptions {
+
+static llvm::cl::list<std::string>
+D_macros("D", llvm::cl::value_desc("macro"), llvm::cl::Prefix,
+ llvm::cl::desc("Predefine the specified macro"));
+
+static llvm::cl::list<std::string>
+ImplicitIncludes("include", llvm::cl::value_desc("file"),
+ llvm::cl::desc("Include file before parsing"));
+static llvm::cl::list<std::string>
+ImplicitMacroIncludes("imacros", llvm::cl::value_desc("file"),
+ llvm::cl::desc("Include macros from file before parsing"));
+
+static llvm::cl::opt<std::string>
+ImplicitIncludePCH("include-pch", llvm::cl::value_desc("file"),
+ llvm::cl::desc("Include precompiled header file"));
+
+static llvm::cl::opt<std::string>
+ImplicitIncludePTH("include-pth", llvm::cl::value_desc("file"),
+ llvm::cl::desc("Include file before parsing"));
+
+static llvm::cl::opt<std::string>
+TokenCache("token-cache", llvm::cl::value_desc("path"),
+ llvm::cl::desc("Use specified token cache file"));
+
+static llvm::cl::list<std::string>
+U_macros("U", llvm::cl::value_desc("macro"), llvm::cl::Prefix,
+ llvm::cl::desc("Undefine the specified macro"));
+
+static llvm::cl::opt<bool>
+UndefMacros("undef", llvm::cl::value_desc("macro"),
+ llvm::cl::desc("undef all system defines"));
+
+}
+
+//===----------------------------------------------------------------------===//
+// Header Search Options
+//===----------------------------------------------------------------------===//
+
+namespace headersearchoptions {
+
+static llvm::cl::opt<bool>
+nostdinc("nostdinc", llvm::cl::desc("Disable standard #include directories"));
+
+static llvm::cl::opt<bool>
+nobuiltininc("nobuiltininc",
+ llvm::cl::desc("Disable builtin #include directories"));
+
+// Various command line options. These four add directories to each chain.
+static llvm::cl::list<std::string>
+F_dirs("F", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
+ llvm::cl::desc("Add directory to framework include search path"));
+
+static llvm::cl::list<std::string>
+I_dirs("I", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
+ llvm::cl::desc("Add directory to include search path"));
+
+static llvm::cl::list<std::string>
+idirafter_dirs("idirafter", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
+ llvm::cl::desc("Add directory to AFTER include search path"));
+
+static llvm::cl::list<std::string>
+iquote_dirs("iquote", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
+ llvm::cl::desc("Add directory to QUOTE include search path"));
+
+static llvm::cl::list<std::string>
+isystem_dirs("isystem", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
+ llvm::cl::desc("Add directory to SYSTEM include search path"));
+
+// These handle -iprefix/-iwithprefix/-iwithprefixbefore.
+static llvm::cl::list<std::string>
+iprefix_vals("iprefix", llvm::cl::value_desc("prefix"), llvm::cl::Prefix,
+ llvm::cl::desc("Set the -iwithprefix/-iwithprefixbefore prefix"));
+static llvm::cl::list<std::string>
+iwithprefix_vals("iwithprefix", llvm::cl::value_desc("dir"), llvm::cl::Prefix,
+ llvm::cl::desc("Set directory to SYSTEM include search path with prefix"));
+static llvm::cl::list<std::string>
+iwithprefixbefore_vals("iwithprefixbefore", llvm::cl::value_desc("dir"),
+ llvm::cl::Prefix,
+ llvm::cl::desc("Set directory to include search path with prefix"));
+
+static llvm::cl::opt<std::string>
+isysroot("isysroot", llvm::cl::value_desc("dir"), llvm::cl::init("/"),
+ llvm::cl::desc("Set the system root directory (usually /)"));
+
+static llvm::cl::opt<bool>
+Verbose("v", llvm::cl::desc("Enable verbose output"));
+
+}
+
+//===----------------------------------------------------------------------===//
+// Preprocessed Output Options
+//===----------------------------------------------------------------------===//
+
+namespace preprocessoroutputoptions {
+
+static llvm::cl::opt<bool>
+DisableLineMarkers("P", llvm::cl::desc("Disable linemarker output in -E mode"));
+
+static llvm::cl::opt<bool>
+EnableCommentOutput("C", llvm::cl::desc("Enable comment output in -E mode"));
+
+static llvm::cl::opt<bool>
+EnableMacroCommentOutput("CC",
+ llvm::cl::desc("Enable comment output in -E mode, "
+ "even from macro expansions"));
+static llvm::cl::opt<bool>
+DumpMacros("dM", llvm::cl::desc("Print macro definitions in -E mode instead of"
+ " normal output"));
+static llvm::cl::opt<bool>
+DumpDefines("dD", llvm::cl::desc("Print macro definitions in -E mode in "
+ "addition to normal output"));
+
+}
+//===----------------------------------------------------------------------===//
+// Target Options
+//===----------------------------------------------------------------------===//
+
+namespace targetoptions {
+
+static llvm::cl::opt<std::string>
+TargetABI("target-abi",
+ llvm::cl::desc("Target a particular ABI type"));
+
+static llvm::cl::opt<std::string>
+TargetCPU("mcpu",
+ llvm::cl::desc("Target a specific cpu type (-mcpu=help for details)"));
+
+static llvm::cl::list<std::string>
+TargetFeatures("target-feature", llvm::cl::desc("Target specific attributes"));
+
+static llvm::cl::opt<std::string>
+TargetTriple("triple",
+ llvm::cl::desc("Specify target triple (e.g. i686-apple-darwin9)"));
+
+}
+
+//===----------------------------------------------------------------------===//
+// Option Object Construction
+//===----------------------------------------------------------------------===//
+
+void clang::InitializeAnalyzerOptions(AnalyzerOptions &Opts) {
+ using namespace analyzeroptions;
+ Opts.AnalysisList = AnalysisList;
+ Opts.AnalysisStoreOpt = AnalysisStoreOpt;
+ Opts.AnalysisConstraintsOpt = AnalysisConstraintsOpt;
+ Opts.AnalysisDiagOpt = AnalysisDiagOpt;
+ Opts.VisualizeEGDot = VisualizeEGDot;
+ Opts.VisualizeEGUbi = VisualizeEGUbi;
+ Opts.AnalyzeAll = AnalyzeAll;
+ Opts.AnalyzerDisplayProgress = AnalyzerDisplayProgress;
+ Opts.PurgeDead = PurgeDead;
+ Opts.EagerlyAssume = EagerlyAssume;
+ Opts.AnalyzeSpecificFunction = AnalyzeSpecificFunction;
+ Opts.EnableExperimentalChecks = AnalyzerExperimentalChecks;
+ Opts.EnableExperimentalInternalChecks = AnalyzerExperimentalInternalChecks;
+ Opts.TrimGraph = TrimGraph;
+}
+
+void clang::InitializeCodeGenOptions(CodeGenOptions &Opts,
+ const LangOptions &Lang,
+ bool TimePasses) {
+ using namespace codegenoptions;
+
+ // -Os implies -O2
+ Opts.OptimizationLevel = OptSize ? 2 : OptLevel;
+
+ // We must always run at least the always inlining pass.
+ Opts.Inlining = (Opts.OptimizationLevel > 1) ? CodeGenOptions::NormalInlining
+ : CodeGenOptions::OnlyAlwaysInlining;
+
+ Opts.DebugInfo = GenerateDebugInfo;
+ Opts.DisableLLVMOpts = DisableLLVMOptimizations;
+ Opts.DisableRedZone = DisableRedZone;
+ Opts.MergeAllConstants = !NoMergeConstants;
+ Opts.NoCommon = NoCommon;
+ Opts.NoImplicitFloat = NoImplicitFloat;
+ Opts.OptimizeSize = OptSize;
+ Opts.SimplifyLibCalls = 1;
+ Opts.UnrollLoops = (Opts.OptimizationLevel > 1 && !OptSize);
+
+ // FIXME: Eliminate this dependency?
+ if (Lang.NoBuiltin)
+ Opts.SimplifyLibCalls = 0;
+ if (Lang.CPlusPlus)
+ Opts.NoCommon = 1;
+ Opts.TimePasses = TimePasses;
+
+#ifdef NDEBUG
+ Opts.VerifyModule = 0;
+#endif
+}
+
+void clang::InitializeDependencyOutputOptions(DependencyOutputOptions &Opts) {
+ using namespace dependencyoutputoptions;
+
+ Opts.OutputFile = DependencyFile;
+ Opts.Targets = DependencyTargets;
+ Opts.IncludeSystemHeaders = DependenciesIncludeSystemHeaders;
+ Opts.UsePhonyTargets = PhonyDependencyTarget;
+}
+
+void clang::InitializeDiagnosticOptions(DiagnosticOptions &Opts) {
+ using namespace diagnosticoptions;
+
+ Opts.Warnings = OptWarnings;
+ Opts.DumpBuildInformation = DumpBuildInformation;
+ Opts.IgnoreWarnings = OptNoWarnings;
+ Opts.MessageLength = MessageLength;
+ Opts.NoRewriteMacros = SilenceRewriteMacroWarning;
+ Opts.Pedantic = OptPedantic;
+ Opts.PedanticErrors = OptPedanticErrors;
+ Opts.ShowCarets = !NoCaretDiagnostics;
+ Opts.ShowColors = PrintColorDiagnostic;
+ Opts.ShowColumn = !NoShowColumn;
+ Opts.ShowFixits = !NoDiagnosticsFixIt;
+ Opts.ShowLocation = !NoShowLocation;
+ Opts.ShowOptionNames = PrintDiagnosticOption;
+ Opts.ShowSourceRanges = PrintSourceRangeInfo;
+ Opts.VerifyDiagnostics = VerifyDiagnostics;
+}
+
+void clang::InitializeFrontendOptions(FrontendOptions &Opts) {
+ using namespace frontendoptions;
+
+ // Select program action.
+ Opts.ProgramAction = ProgAction;
+ if (PluginActionName.getPosition()) {
+ Opts.ProgramAction = frontend::PluginAction;
+ Opts.ActionName = PluginActionName;
+ }
+
+ Opts.CodeCompletionAt = CodeCompletionAt;
+ Opts.DebugCodeCompletionPrinter = CodeCompletionDebugPrinter;
+ Opts.DisableFree = DisableFree;
+ Opts.EmptyInputOnly = EmptyInputOnly;
+ Opts.FixItLocations = FixItAtLocations;
+ Opts.OutputFile = OutputFile;
+ Opts.RelocatablePCH = RelocatablePCH;
+ Opts.ShowMacrosInCodeCompletion = CodeCompletionWantsMacros;
+ Opts.ShowStats = Stats;
+ Opts.ShowTimers = TimeReport;
+ Opts.ViewClassInheritance = InheritanceViewCls;
+
+ // '-' is the default input if none is given.
+ if (InputFilenames.empty()) {
+ FrontendOptions::InputKind IK = InputType;
+ if (IK == FrontendOptions::IK_None) IK = FrontendOptions::IK_C;
+ Opts.Inputs.push_back(std::make_pair(IK, "-"));
+ } else {
+ for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) {
+ FrontendOptions::InputKind IK = InputType;
+ llvm::StringRef Ext =
+ llvm::StringRef(InputFilenames[i]).rsplit('.').second;
+ if (IK == FrontendOptions::IK_None)
+ IK = FrontendOptions::getInputKindForExtension(Ext);
+ Opts.Inputs.push_back(std::make_pair(IK, InputFilenames[i]));
+ }
+ }
+}
+
+void clang::InitializeHeaderSearchOptions(HeaderSearchOptions &Opts,
+ llvm::StringRef BuiltinIncludePath) {
+ using namespace headersearchoptions;
+
+ Opts.Sysroot = isysroot;
+ Opts.Verbose = Verbose;
+
+ // Handle -I... and -F... options, walking the lists in parallel.
+ unsigned Iidx = 0, Fidx = 0;
+ while (Iidx < I_dirs.size() && Fidx < F_dirs.size()) {
+ if (I_dirs.getPosition(Iidx) < F_dirs.getPosition(Fidx)) {
+ Opts.AddPath(I_dirs[Iidx], frontend::Angled, true, false);
+ ++Iidx;
+ } else {
+ Opts.AddPath(F_dirs[Fidx], frontend::Angled, true, true);
+ ++Fidx;
+ }
+ }
+
+ // Consume what's left from whatever list was longer.
+ for (; Iidx != I_dirs.size(); ++Iidx)
+ Opts.AddPath(I_dirs[Iidx], frontend::Angled, true, false);
+ for (; Fidx != F_dirs.size(); ++Fidx)
+ Opts.AddPath(F_dirs[Fidx], frontend::Angled, true, true);
+
+ // Handle -idirafter... options.
+ for (unsigned i = 0, e = idirafter_dirs.size(); i != e; ++i)
+ Opts.AddPath(idirafter_dirs[i], frontend::After, true, false);
+
+ // Handle -iquote... options.
+ for (unsigned i = 0, e = iquote_dirs.size(); i != e; ++i)
+ Opts.AddPath(iquote_dirs[i], frontend::Quoted, true, false);
+
+ // Handle -isystem... options.
+ for (unsigned i = 0, e = isystem_dirs.size(); i != e; ++i)
+ Opts.AddPath(isystem_dirs[i], frontend::System, true, false);
+
+ // Walk the -iprefix/-iwithprefix/-iwithprefixbefore argument lists in
+ // parallel, processing the values in order of occurance to get the right
+ // prefixes.
+ {
+ std::string Prefix = ""; // FIXME: this isn't the correct default prefix.
+ unsigned iprefix_idx = 0;
+ unsigned iwithprefix_idx = 0;
+ unsigned iwithprefixbefore_idx = 0;
+ bool iprefix_done = iprefix_vals.empty();
+ bool iwithprefix_done = iwithprefix_vals.empty();
+ bool iwithprefixbefore_done = iwithprefixbefore_vals.empty();
+ while (!iprefix_done || !iwithprefix_done || !iwithprefixbefore_done) {
+ if (!iprefix_done &&
+ (iwithprefix_done ||
+ iprefix_vals.getPosition(iprefix_idx) <
+ iwithprefix_vals.getPosition(iwithprefix_idx)) &&
+ (iwithprefixbefore_done ||
+ iprefix_vals.getPosition(iprefix_idx) <
+ iwithprefixbefore_vals.getPosition(iwithprefixbefore_idx))) {
+ Prefix = iprefix_vals[iprefix_idx];
+ ++iprefix_idx;
+ iprefix_done = iprefix_idx == iprefix_vals.size();
+ } else if (!iwithprefix_done &&
+ (iwithprefixbefore_done ||
+ iwithprefix_vals.getPosition(iwithprefix_idx) <
+ iwithprefixbefore_vals.getPosition(iwithprefixbefore_idx))) {
+ Opts.AddPath(Prefix+iwithprefix_vals[iwithprefix_idx],
+ frontend::System, false, false);
+ ++iwithprefix_idx;
+ iwithprefix_done = iwithprefix_idx == iwithprefix_vals.size();
+ } else {
+ Opts.AddPath(Prefix+iwithprefixbefore_vals[iwithprefixbefore_idx],
+ frontend::Angled, false, false);
+ ++iwithprefixbefore_idx;
+ iwithprefixbefore_done =
+ iwithprefixbefore_idx == iwithprefixbefore_vals.size();
+ }
+ }
+ }
+
+ // Add CPATH environment paths.
+ if (const char *Env = getenv("CPATH"))
+ Opts.EnvIncPath = Env;
+
+ // Add language specific environment paths.
+ if (const char *Env = getenv("OBJCPLUS_INCLUDE_PATH"))
+ Opts.ObjCXXEnvIncPath = Env;
+ if (const char *Env = getenv("CPLUS_INCLUDE_PATH"))
+ Opts.CXXEnvIncPath = Env;
+ if (const char *Env = getenv("OBJC_INCLUDE_PATH"))
+ Opts.CEnvIncPath = Env;
+ if (const char *Env = getenv("C_INCLUDE_PATH"))
+ Opts.CEnvIncPath = Env;
+
+ if (!nobuiltininc)
+ Opts.BuiltinIncludePath = BuiltinIncludePath;
+
+ Opts.UseStandardIncludes = !nostdinc;
+}
+
+void clang::InitializePreprocessorOptions(PreprocessorOptions &Opts) {
+ using namespace preprocessoroptions;
+
+ Opts.ImplicitPCHInclude = ImplicitIncludePCH;
+ Opts.ImplicitPTHInclude = ImplicitIncludePTH;
+
+ // Select the token cache file, we don't support more than one currently so we
+ // can't have both an implicit-pth and a token cache file.
+ if (TokenCache.getPosition() && ImplicitIncludePTH.getPosition()) {
+ // FIXME: Don't fail like this.
+ fprintf(stderr, "error: cannot use both -token-cache and -include-pth "
+ "options\n");
+ exit(1);
+ }
+ if (TokenCache.getPosition())
+ Opts.TokenCache = TokenCache;
+ else
+ Opts.TokenCache = ImplicitIncludePTH;
+
+ // Use predefines?
+ Opts.UsePredefines = !UndefMacros;
+
+ // Add macros from the command line.
+ unsigned d = 0, D = D_macros.size();
+ unsigned u = 0, U = U_macros.size();
+ while (d < D || u < U) {
+ if (u == U || (d < D && D_macros.getPosition(d) < U_macros.getPosition(u)))
+ Opts.addMacroDef(D_macros[d++]);
+ else
+ Opts.addMacroUndef(U_macros[u++]);
+ }
+
+ // If -imacros are specified, include them now. These are processed before
+ // any -include directives.
+ for (unsigned i = 0, e = ImplicitMacroIncludes.size(); i != e; ++i)
+ Opts.MacroIncludes.push_back(ImplicitMacroIncludes[i]);
+
+ // Add the ordered list of -includes, sorting in the implicit include options
+ // at the appropriate location.
+ llvm::SmallVector<std::pair<unsigned, std::string*>, 8> OrderedPaths;
+ std::string OriginalFile;
+
+ if (!ImplicitIncludePTH.empty())
+ OrderedPaths.push_back(std::make_pair(ImplicitIncludePTH.getPosition(),
+ &ImplicitIncludePTH));
+ if (!ImplicitIncludePCH.empty()) {
+ OriginalFile = PCHReader::getOriginalSourceFile(ImplicitIncludePCH);
+ // FIXME: Don't fail like this.
+ if (OriginalFile.empty())
+ exit(1);
+ OrderedPaths.push_back(std::make_pair(ImplicitIncludePCH.getPosition(),
+ &OriginalFile));
+ }
+ for (unsigned i = 0, e = ImplicitIncludes.size(); i != e; ++i)
+ OrderedPaths.push_back(std::make_pair(ImplicitIncludes.getPosition(i),
+ &ImplicitIncludes[i]));
+ llvm::array_pod_sort(OrderedPaths.begin(), OrderedPaths.end());
+
+ for (unsigned i = 0, e = OrderedPaths.size(); i != e; ++i)
+ Opts.Includes.push_back(*OrderedPaths[i].second);
+}
+
+void clang::InitializeLangOptions(LangOptions &Options,
+ FrontendOptions::InputKind IK,
+ TargetInfo &Target) {
+ using namespace langoptions;
+
+
+ switch (IK) {
+ case FrontendOptions::IK_None:
+ case FrontendOptions::IK_AST:
+ assert(0 && "Invalid input kind!");
+ case FrontendOptions::IK_Asm:
+ Options.AsmPreprocessor = 1;
+ // FALLTHROUGH
+ case FrontendOptions::IK_PreprocessedC:
+ // FALLTHROUGH
+ case FrontendOptions::IK_C:
+ // Do nothing.
+ break;
+ case FrontendOptions::IK_PreprocessedCXX:
+ // FALLTHROUGH
+ case FrontendOptions::IK_CXX:
+ Options.CPlusPlus = 1;
+ break;
+ case FrontendOptions::IK_PreprocessedObjC:
+ // FALLTHROUGH
+ case FrontendOptions::IK_ObjC:
+ Options.ObjC1 = Options.ObjC2 = 1;
+ break;
+ case FrontendOptions::IK_PreprocessedObjCXX:
+ // FALLTHROUGH
+ case FrontendOptions::IK_ObjCXX:
+ Options.ObjC1 = Options.ObjC2 = 1;
+ Options.CPlusPlus = 1;
+ break;
+ case FrontendOptions::IK_OpenCL:
+ Options.OpenCL = 1;
+ Options.AltiVec = 1;
+ Options.CXXOperatorNames = 1;
+ Options.LaxVectorConversions = 1;
+ break;
+ }
+
+ if (ObjCExclusiveGC)
+ Options.setGCMode(LangOptions::GCOnly);
+ else if (ObjCEnableGC)
+ Options.setGCMode(LangOptions::HybridGC);
+
+ if (ObjCEnableGCBitmapPrint)
+ Options.ObjCGCBitmapPrint = 1;
+
+ if (AltiVec)
+ Options.AltiVec = 1;
+
+ if (PThread)
+ Options.POSIXThreads = 1;
+
+ Options.setVisibilityMode(SymbolVisibility);
+ Options.OverflowChecking = OverflowChecking;
+
+ if (LangStd == lang_unspecified) {
+ // Based on the base language, pick one.
+ switch (IK) {
+ case FrontendOptions::IK_None:
+ case FrontendOptions::IK_AST:
+ assert(0 && "Invalid input kind!");
+ case FrontendOptions::IK_OpenCL:
+ LangStd = lang_c99;
+ break;
+ case FrontendOptions::IK_Asm:
+ case FrontendOptions::IK_C:
+ case FrontendOptions::IK_PreprocessedC:
+ case FrontendOptions::IK_ObjC:
+ case FrontendOptions::IK_PreprocessedObjC:
+ LangStd = lang_gnu99;
+ break;
+ case FrontendOptions::IK_CXX:
+ case FrontendOptions::IK_PreprocessedCXX:
+ case FrontendOptions::IK_ObjCXX:
+ case FrontendOptions::IK_PreprocessedObjCXX:
+ LangStd = lang_gnucxx98;
+ break;
+ }
+ }
+
+ switch (LangStd) {
+ default: assert(0 && "Unknown language standard!");
+
+ // Fall through from newer standards to older ones. This isn't really right.
+ // FIXME: Enable specifically the right features based on the language stds.
+ case lang_gnucxx0x:
+ case lang_cxx0x:
+ Options.CPlusPlus0x = 1;
+ // FALL THROUGH
+ case lang_gnucxx98:
+ case lang_cxx98:
+ Options.CPlusPlus = 1;
+ Options.CXXOperatorNames = !NoOperatorNames;
+ // FALL THROUGH.
+ case lang_gnu99:
+ case lang_c99:
+ Options.C99 = 1;
+ Options.HexFloats = 1;
+ // FALL THROUGH.
+ case lang_gnu89:
+ Options.BCPLComment = 1; // Only for C99/C++.
+ // FALL THROUGH.
+ case lang_c94:
+ Options.Digraphs = 1; // C94, C99, C++.
+ // FALL THROUGH.
+ case lang_c89:
+ break;
+ }
+
+ // GNUMode - Set if we're in gnu99, gnu89, gnucxx98, etc.
+ switch (LangStd) {
+ default: assert(0 && "Unknown language standard!");
+ case lang_gnucxx0x:
+ case lang_gnucxx98:
+ case lang_gnu99:
+ case lang_gnu89:
+ Options.GNUMode = 1;
+ break;
+ case lang_cxx0x:
+ case lang_cxx98:
+ case lang_c99:
+ case lang_c94:
+ case lang_c89:
+ Options.GNUMode = 0;
+ break;
+ }
+
+ if (Options.CPlusPlus) {
+ Options.C99 = 0;
+ Options.HexFloats = 0;
+ }
+
+ if (LangStd == lang_c89 || LangStd == lang_c94 || LangStd == lang_gnu89)
+ Options.ImplicitInt = 1;
+ else
+ Options.ImplicitInt = 0;
+
+ // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs
+ // is specified, or -std is set to a conforming mode.
+ Options.Trigraphs = !Options.GNUMode;
+ if (Trigraphs.getPosition())
+ Options.Trigraphs = Trigraphs; // Command line option wins if specified.
+
+ // If in a conformant language mode (e.g. -std=c99) Blocks defaults to off
+ // even if they are normally on for the target. In GNU modes (e.g.
+ // -std=gnu99) the default for blocks depends on the target settings.
+ // However, blocks are not turned off when compiling Obj-C or Obj-C++ code.
+ if (!Options.ObjC1 && !Options.GNUMode)
+ Options.Blocks = 0;
+
+ // Default to not accepting '$' in identifiers when preprocessing assembler,
+ // but do accept when preprocessing C. FIXME: these defaults are right for
+ // darwin, are they right everywhere?
+ Options.DollarIdents = IK != FrontendOptions::IK_Asm;
+ if (DollarsInIdents.getPosition()) // Explicit setting overrides default.
+ Options.DollarIdents = DollarsInIdents;
+
+ if (PascalStrings.getPosition())
+ Options.PascalStrings = PascalStrings;
+ if (MSExtensions.getPosition())
+ Options.Microsoft = MSExtensions;
+ Options.WritableStrings = WritableStrings;
+ if (NoLaxVectorConversions.getPosition())
+ Options.LaxVectorConversions = 0;
+ Options.Exceptions = Exceptions;
+ Options.Rtti = Rtti;
+ if (EnableBlocks.getPosition())
+ Options.Blocks = EnableBlocks;
+ if (CharIsSigned.getPosition())
+ Options.CharIsSigned = CharIsSigned;
+ if (ShortWChar.getPosition())
+ Options.ShortWChar = ShortWChar;
+
+ if (!AllowBuiltins)
+ Options.NoBuiltin = 1;
+ if (Freestanding)
+ Options.Freestanding = Options.NoBuiltin = 1;
+
+ if (EnableHeinousExtensions)
+ Options.HeinousExtensions = 1;
+
+ if (AccessControl)
+ Options.AccessControl = 1;
+
+ Options.ElideConstructors = !NoElideConstructors;
+
+ // OpenCL and C++ both have bool, true, false keywords.
+ Options.Bool = Options.OpenCL | Options.CPlusPlus;
+
+ Options.MathErrno = MathErrno;
+
+ Options.InstantiationDepth = TemplateDepth;
+
+ // Override the default runtime if the user requested it.
+ if (GNURuntime)
+ Options.NeXTRuntime = 0;
+
+ if (!ObjCConstantStringClass.empty())
+ Options.ObjCConstantStringClass = ObjCConstantStringClass.c_str();
+
+ if (ObjCNonFragileABI)
+ Options.ObjCNonFragileABI = 1;
+
+ if (EmitAllDecls)
+ Options.EmitAllDecls = 1;
+
+ // The __OPTIMIZE_SIZE__ define is tied to -Oz, which we don't support.
+ Options.OptimizeSize = 0;
+ Options.Optimize = codegenoptions::OptSize || codegenoptions::OptLevel;
+
+ assert(PICLevel <= 2 && "Invalid value for -pic-level");
+ Options.PICLevel = PICLevel;
+
+ Options.GNUInline = !Options.C99;
+
+ // This is the __NO_INLINE__ define, which just depends on things like the
+ // optimization level and -fno-inline, not actually whether the backend has
+ // inlining enabled.
+ //
+ // FIXME: This is affected by other options (-fno-inline).
+ Options.NoInline = !codegenoptions::OptLevel;
+
+ Options.Static = StaticDefine;
+
+ switch (StackProtector) {
+ default:
+ assert(StackProtector <= 2 && "Invalid value for -stack-protector");
+ case -1: break;
+ case 0: Options.setStackProtectorMode(LangOptions::SSPOff); break;
+ case 1: Options.setStackProtectorMode(LangOptions::SSPOn); break;
+ case 2: Options.setStackProtectorMode(LangOptions::SSPReq); break;
+ }
+
+ if (MainFileName.getPosition())
+ Options.setMainFileName(MainFileName.c_str());
+
+ Target.setForcedLangOptions(Options);
+}
+
+void
+clang::InitializePreprocessorOutputOptions(PreprocessorOutputOptions &Opts) {
+ using namespace preprocessoroutputoptions;
+
+ Opts.ShowCPP = !DumpMacros;
+ Opts.ShowMacros = DumpMacros || DumpDefines;
+ Opts.ShowLineMarkers = !DisableLineMarkers;
+ Opts.ShowComments = EnableCommentOutput;
+ Opts.ShowMacroComments = EnableMacroCommentOutput;
+}
+
+void clang::InitializeTargetOptions(TargetOptions &Opts) {
+ using namespace targetoptions;
+
+ Opts.ABI = TargetABI;
+ Opts.CPU = TargetCPU;
+ Opts.Triple = TargetTriple;
+ Opts.Features = TargetFeatures;
+
+ // Use the host triple if unspecified.
+ if (Opts.Triple.empty())
+ Opts.Triple = llvm::sys::getHostTriple();
+}
diff --git a/tools/clang-cc/Options.h b/tools/clang-cc/Options.h
new file mode 100644
index 0000000..9a2fd9d
--- /dev/null
+++ b/tools/clang-cc/Options.h
@@ -0,0 +1,57 @@
+//===-- Options.h - clang-cc Option Handling --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANGCC_OPTIONS_H
+#define LLVM_CLANGCC_OPTIONS_H
+
+#include "clang/Frontend/FrontendOptions.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+
+class AnalyzerOptions;
+class CodeGenOptions;
+class DependencyOutputOptions;
+class DiagnosticOptions;
+class FrontendOptions;
+class HeaderSearchOptions;
+class LangOptions;
+class PreprocessorOptions;
+class PreprocessorOutputOptions;
+class TargetInfo;
+class TargetOptions;
+
+void InitializeAnalyzerOptions(AnalyzerOptions &Opts);
+
+void InitializeCodeGenOptions(CodeGenOptions &Opts,
+ const LangOptions &Lang,
+ bool TimePasses);
+
+void InitializeDependencyOutputOptions(DependencyOutputOptions &Opts);
+
+void InitializeDiagnosticOptions(DiagnosticOptions &Opts);
+
+void InitializeFrontendOptions(FrontendOptions &Opts);
+
+void InitializeHeaderSearchOptions(HeaderSearchOptions &Opts,
+ llvm::StringRef BuiltinIncludePath);
+
+void InitializeLangOptions(LangOptions &Options,
+ FrontendOptions::InputKind LK,
+ TargetInfo &Target);
+
+void InitializePreprocessorOptions(PreprocessorOptions &Opts);
+
+void InitializePreprocessorOutputOptions(PreprocessorOutputOptions &Opts);
+
+void InitializeTargetOptions(TargetOptions &Opts);
+
+} // end namespace clang
+
+#endif
diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp
index 26ba42d..bae8697 100644
--- a/tools/clang-cc/clang-cc.cpp
+++ b/tools/clang-cc/clang-cc.cpp
@@ -8,2122 +8,198 @@
//===----------------------------------------------------------------------===//
//
// This utility may be invoked in the following manner:
-// clang --help - Output help info.
-// clang [options] - Read from stdin.
-// clang [options] file - Read from "file".
-// clang [options] file1 file2 - Read these files.
-//
-//===----------------------------------------------------------------------===//
-//
-// TODO: Options to support:
-//
-// -Wfatal-errors
-// -ftabstop=width
+// clang-cc --help - Output help info.
+// clang-cc [options] - Read from stdin.
+// clang-cc [options] file - Read from "file".
+// clang-cc [options] file1 file2 - Read these files.
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/AnalysisConsumer.h"
-#include "clang/Frontend/ASTConsumers.h"
-#include "clang/Frontend/ASTUnit.h"
-#include "clang/Frontend/CompileOptions.h"
-#include "clang/Frontend/DiagnosticOptions.h"
-#include "clang/Frontend/FixItRewriter.h"
-#include "clang/Frontend/FrontendDiagnostic.h"
-#include "clang/Frontend/InitHeaderSearch.h"
-#include "clang/Frontend/InitPreprocessor.h"
-#include "clang/Frontend/PathDiagnosticClients.h"
-#include "clang/Frontend/PCHReader.h"
-#include "clang/Frontend/TextDiagnosticBuffer.h"
-#include "clang/Frontend/TextDiagnosticPrinter.h"
-#include "clang/Frontend/CommandLineSourceLoc.h"
-#include "clang/Frontend/Utils.h"
-#include "clang/Analysis/PathDiagnostic.h"
-#include "clang/CodeGen/ModuleBuilder.h"
-#include "clang/Sema/CodeCompleteConsumer.h"
-#include "clang/Sema/ParseAST.h"
-#include "clang/Sema/SemaDiagnostic.h"
-#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclGroup.h"
-#include "clang/Parse/Parser.h"
-#include "clang/Lex/HeaderSearch.h"
-#include "clang/Lex/LexDiagnostic.h"
+#include "Options.h"
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/FrontendPluginRegistry.h"
+#include "clang/Frontend/VerifyDiagnosticsClient.h"
#include "llvm/LLVMContext.h"
#include "llvm/ADT/OwningPtr.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Host.h"
#include "llvm/System/Path.h"
-#include "llvm/System/Program.h"
#include "llvm/System/Signals.h"
#include "llvm/Target/TargetSelect.h"
-#include <cstdlib>
-#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
using namespace clang;
//===----------------------------------------------------------------------===//
-// Source Location Parser
-//===----------------------------------------------------------------------===//
-
-static bool ResolveParsedLocation(ParsedSourceLocation &ParsedLoc,
- FileManager &FileMgr,
- RequestedSourceLocation &Result) {
- const FileEntry *File = FileMgr.getFile(ParsedLoc.FileName);
- if (!File)
- return true;
-
- Result.File = File;
- Result.Line = ParsedLoc.Line;
- Result.Column = ParsedLoc.Column;
- return false;
-}
-
-//===----------------------------------------------------------------------===//
-// Global options.
-//===----------------------------------------------------------------------===//
-
-/// ClangFrontendTimer - The front-end activities should charge time to it with
-/// TimeRegion. The -ftime-report option controls whether this will do
-/// anything.
-llvm::Timer *ClangFrontendTimer = 0;
-
-static llvm::cl::opt<bool>
-Verbose("v", llvm::cl::desc("Enable verbose output"));
-static llvm::cl::opt<bool>
-Stats("print-stats",
- llvm::cl::desc("Print performance metrics and statistics"));
-static llvm::cl::opt<bool>
-DisableFree("disable-free",
- llvm::cl::desc("Disable freeing of memory on exit"),
- llvm::cl::init(false));
-static llvm::cl::opt<bool>
-EmptyInputOnly("empty-input-only",
- llvm::cl::desc("Force running on an empty input file"));
-
-enum ProgActions {
- RewriteObjC, // ObjC->C Rewriter.
- RewriteBlocks, // ObjC->C Rewriter for Blocks.
- RewriteMacros, // Expand macros but not #includes.
- RewriteTest, // Rewriter playground
- FixIt, // Fix-It Rewriter
- HTMLTest, // HTML displayer testing stuff.
- EmitAssembly, // Emit a .s file.
- EmitLLVM, // Emit a .ll file.
- EmitBC, // Emit a .bc file.
- EmitLLVMOnly, // Generate LLVM IR, but do not
- EmitHTML, // Translate input source into HTML.
- ASTPrint, // Parse ASTs and print them.
- ASTPrintXML, // Parse ASTs and print them in XML.
- ASTDump, // Parse ASTs and dump them.
- ASTView, // Parse ASTs and view them in Graphviz.
- PrintDeclContext, // Print DeclContext and their Decls.
- DumpRecordLayouts, // Dump record layout information.
- ParsePrintCallbacks, // Parse and print each callback.
- ParseSyntaxOnly, // Parse and perform semantic analysis.
- ParseNoop, // Parse with noop callbacks.
- RunPreprocessorOnly, // Just lex, no output.
- PrintPreprocessedInput, // -E mode.
- DumpTokens, // Dump out preprocessed tokens.
- DumpRawTokens, // Dump out raw tokens.
- RunAnalysis, // Run one or more source code analyses.
- GeneratePTH, // Generate pre-tokenized header.
- GeneratePCH, // Generate pre-compiled header.
- InheritanceView // View C++ inheritance for a specified class.
-};
-
-static llvm::cl::opt<ProgActions>
-ProgAction(llvm::cl::desc("Choose output type:"), llvm::cl::ZeroOrMore,
- llvm::cl::init(ParseSyntaxOnly),
- llvm::cl::values(
- clEnumValN(RunPreprocessorOnly, "Eonly",
- "Just run preprocessor, no output (for timings)"),
- clEnumValN(PrintPreprocessedInput, "E",
- "Run preprocessor, emit preprocessed file"),
- clEnumValN(DumpRawTokens, "dump-raw-tokens",
- "Lex file in raw mode and dump raw tokens"),
- clEnumValN(RunAnalysis, "analyze",
- "Run static analysis engine"),
- clEnumValN(DumpTokens, "dump-tokens",
- "Run preprocessor, dump internal rep of tokens"),
- clEnumValN(ParseNoop, "parse-noop",
- "Run parser with noop callbacks (for timings)"),
- clEnumValN(ParseSyntaxOnly, "fsyntax-only",
- "Run parser and perform semantic analysis"),
- clEnumValN(ParsePrintCallbacks, "parse-print-callbacks",
- "Run parser and print each callback invoked"),
- clEnumValN(EmitHTML, "emit-html",
- "Output input source as HTML"),
- clEnumValN(ASTPrint, "ast-print",
- "Build ASTs and then pretty-print them"),
- clEnumValN(ASTPrintXML, "ast-print-xml",
- "Build ASTs and then print them in XML format"),
- clEnumValN(ASTDump, "ast-dump",
- "Build ASTs and then debug dump them"),
- clEnumValN(ASTView, "ast-view",
- "Build ASTs and view them with GraphViz"),
- clEnumValN(PrintDeclContext, "print-decl-contexts",
- "Print DeclContexts and their Decls"),
- clEnumValN(DumpRecordLayouts, "dump-record-layouts",
- "Dump record layout information"),
- clEnumValN(GeneratePTH, "emit-pth",
- "Generate pre-tokenized header file"),
- clEnumValN(GeneratePCH, "emit-pch",
- "Generate pre-compiled header file"),
- clEnumValN(EmitAssembly, "S",
- "Emit native assembly code"),
- clEnumValN(EmitLLVM, "emit-llvm",
- "Build ASTs then convert to LLVM, emit .ll file"),
- clEnumValN(EmitBC, "emit-llvm-bc",
- "Build ASTs then convert to LLVM, emit .bc file"),
- clEnumValN(EmitLLVMOnly, "emit-llvm-only",
- "Build ASTs and convert to LLVM, discarding output"),
- clEnumValN(RewriteTest, "rewrite-test",
- "Rewriter playground"),
- clEnumValN(RewriteObjC, "rewrite-objc",
- "Rewrite ObjC into C (code rewriter example)"),
- clEnumValN(RewriteMacros, "rewrite-macros",
- "Expand macros without full preprocessing"),
- clEnumValN(RewriteBlocks, "rewrite-blocks",
- "Rewrite Blocks to C"),
- clEnumValN(FixIt, "fixit",
- "Apply fix-it advice to the input source"),
- clEnumValEnd));
-
-
-static llvm::cl::opt<std::string>
-OutputFile("o",
- llvm::cl::value_desc("path"),
- llvm::cl::desc("Specify output file"));
-
-
-static llvm::cl::opt<ParsedSourceLocation>
-CodeCompletionAt("code-completion-at",
- llvm::cl::value_desc("file:line:column"),
- llvm::cl::desc("Dump code-completion information at a location"));
-
-/// \brief Buld a new code-completion consumer that prints the results of
-/// code completion to standard output.
-static CodeCompleteConsumer *BuildPrintingCodeCompleter(Sema &S, void *) {
- return new PrintingCodeCompleteConsumer(S, llvm::outs());
-}
-
-//===----------------------------------------------------------------------===//
-// PTH.
-//===----------------------------------------------------------------------===//
-
-static llvm::cl::opt<std::string>
-TokenCache("token-cache", llvm::cl::value_desc("path"),
- llvm::cl::desc("Use specified token cache file"));
-
-//===----------------------------------------------------------------------===//
-// Diagnostic Options
-//===----------------------------------------------------------------------===//
-
-static DiagnosticOptions DiagOpts;
-
-static llvm::cl::opt<bool>
-VerifyDiagnostics("verify",
- llvm::cl::desc("Verify emitted diagnostics and warnings"));
-
-static llvm::cl::opt<bool>
-NoShowColumn("fno-show-column",
- llvm::cl::desc("Do not include column number on diagnostics"));
-
-static llvm::cl::opt<bool>
-NoShowLocation("fno-show-source-location",
- llvm::cl::desc("Do not include source location information with"
- " diagnostics"));
-
-static llvm::cl::opt<bool>
-NoCaretDiagnostics("fno-caret-diagnostics",
- llvm::cl::desc("Do not include source line and caret with"
- " diagnostics"));
-
-static llvm::cl::opt<bool>
-NoDiagnosticsFixIt("fno-diagnostics-fixit-info",
- llvm::cl::desc("Do not include fixit information in"
- " diagnostics"));
-
-static llvm::cl::opt<bool>
-PrintSourceRangeInfo("fdiagnostics-print-source-range-info",
- llvm::cl::desc("Print source range spans in numeric form"));
-
-static llvm::cl::opt<bool>
-PrintDiagnosticOption("fdiagnostics-show-option",
- llvm::cl::desc("Print diagnostic name with mappable diagnostics"));
-
-static llvm::cl::opt<unsigned>
-MessageLength("fmessage-length",
- llvm::cl::desc("Format message diagnostics so that they fit "
- "within N columns or fewer, when possible."),
- llvm::cl::value_desc("N"));
-
-static llvm::cl::opt<bool>
-PrintColorDiagnostic("fcolor-diagnostics",
- llvm::cl::desc("Use colors in diagnostics"));
-
-//===----------------------------------------------------------------------===//
-// C++ Visualization.
-//===----------------------------------------------------------------------===//
-
-static llvm::cl::opt<std::string>
-InheritanceViewCls("cxx-inheritance-view",
- llvm::cl::value_desc("class name"),
- llvm::cl::desc("View C++ inheritance for a specified class"));
-
-//===----------------------------------------------------------------------===//
-// Builtin Options
-//===----------------------------------------------------------------------===//
-
-static llvm::cl::opt<bool>
-TimeReport("ftime-report",
- llvm::cl::desc("Print the amount of time each "
- "phase of compilation takes"));
-
-static llvm::cl::opt<bool>
-Freestanding("ffreestanding",
- llvm::cl::desc("Assert that the compilation takes place in a "
- "freestanding environment"));
-
-static llvm::cl::opt<bool>
-AllowBuiltins("fbuiltin", llvm::cl::init(true),
- llvm::cl::desc("Disable implicit builtin knowledge of functions"));
-
-
-static llvm::cl::opt<bool>
-MathErrno("fmath-errno", llvm::cl::init(true),
- llvm::cl::desc("Require math functions to respect errno"));
-
-//===----------------------------------------------------------------------===//
-// Language Options
-//===----------------------------------------------------------------------===//
-
-enum LangKind {
- langkind_unspecified,
- langkind_c,
- langkind_c_cpp,
- langkind_asm_cpp,
- langkind_cxx,
- langkind_cxx_cpp,
- langkind_objc,
- langkind_objc_cpp,
- langkind_objcxx,
- langkind_objcxx_cpp,
- langkind_ocl,
- langkind_ast
-};
-
-static llvm::cl::opt<LangKind>
-BaseLang("x", llvm::cl::desc("Base language to compile"),
- llvm::cl::init(langkind_unspecified),
- llvm::cl::values(clEnumValN(langkind_c, "c", "C"),
- clEnumValN(langkind_ocl, "cl", "OpenCL C"),
- clEnumValN(langkind_cxx, "c++", "C++"),
- clEnumValN(langkind_objc, "objective-c", "Objective C"),
- clEnumValN(langkind_objcxx,"objective-c++","Objective C++"),
- clEnumValN(langkind_c_cpp, "cpp-output",
- "Preprocessed C"),
- clEnumValN(langkind_asm_cpp, "assembler-with-cpp",
- "Preprocessed asm"),
- clEnumValN(langkind_cxx_cpp, "c++-cpp-output",
- "Preprocessed C++"),
- clEnumValN(langkind_objc_cpp, "objective-c-cpp-output",
- "Preprocessed Objective C"),
- clEnumValN(langkind_objcxx_cpp, "objective-c++-cpp-output",
- "Preprocessed Objective C++"),
- clEnumValN(langkind_c, "c-header",
- "C header"),
- clEnumValN(langkind_objc, "objective-c-header",
- "Objective-C header"),
- clEnumValN(langkind_cxx, "c++-header",
- "C++ header"),
- clEnumValN(langkind_objcxx, "objective-c++-header",
- "Objective-C++ header"),
- clEnumValN(langkind_ast, "ast",
- "Clang AST"),
- clEnumValEnd));
-
-static llvm::cl::opt<bool>
-ObjCExclusiveGC("fobjc-gc-only",
- llvm::cl::desc("Use GC exclusively for Objective-C related "
- "memory management"));
-
-static llvm::cl::opt<std::string>
-ObjCConstantStringClass("fconstant-string-class",
- llvm::cl::value_desc("class name"),
- llvm::cl::desc("Specify the class to use for constant "
- "Objective-C string objects."));
-
-static llvm::cl::opt<bool>
-ObjCEnableGC("fobjc-gc",
- llvm::cl::desc("Enable Objective-C garbage collection"));
-
-static llvm::cl::opt<bool>
-ObjCEnableGCBitmapPrint("print-ivar-layout",
- llvm::cl::desc("Enable Objective-C Ivar layout bitmap print trace"));
-
-static llvm::cl::opt<LangOptions::VisibilityMode>
-SymbolVisibility("fvisibility",
- llvm::cl::desc("Set the default symbol visibility:"),
- llvm::cl::init(LangOptions::Default),
- llvm::cl::values(clEnumValN(LangOptions::Default, "default",
- "Use default symbol visibility"),
- clEnumValN(LangOptions::Hidden, "hidden",
- "Use hidden symbol visibility"),
- clEnumValN(LangOptions::Protected,"protected",
- "Use protected symbol visibility"),
- clEnumValEnd));
-
-static llvm::cl::opt<bool>
-OverflowChecking("ftrapv",
- llvm::cl::desc("Trap on integer overflow"),
- llvm::cl::init(false));
-
-static llvm::cl::opt<bool>
-AltiVec("faltivec", llvm::cl::desc("Enable AltiVec vector initializer syntax"),
- llvm::cl::init(false));
-
-static llvm::cl::opt<bool>
-PThread("pthread", llvm::cl::desc("Support POSIX threads in generated code"),
- llvm::cl::init(false));
-
-static LangKind GetLanguage(llvm::StringRef Filename) {
- if (BaseLang != langkind_unspecified)
- return BaseLang;
-
- llvm::StringRef Ext = Filename.rsplit('.').second;
- if (Ext == "ast")
- return langkind_ast;
- else if (Ext == "c")
- return langkind_c;
- else if (Ext == "S" || Ext == "s")
- return langkind_asm_cpp;
- else if (Ext == "i")
- return langkind_c_cpp;
- else if (Ext == "ii")
- return langkind_cxx_cpp;
- else if (Ext == "m")
- return langkind_objc;
- else if (Ext == "mi")
- return langkind_objc_cpp;
- else if (Ext == "mm" || Ext == "M")
- return langkind_objcxx;
- else if (Ext == "mii")
- return langkind_objcxx_cpp;
- else if (Ext == "C" || Ext == "cc" || Ext == "cpp" || Ext == "CPP" ||
- Ext == "c++" || Ext == "cp" || Ext == "cxx")
- return langkind_cxx;
- else if (Ext == "cl")
- return langkind_ocl;
- else
- return langkind_c;
-}
-
-
-static void InitializeCOptions(LangOptions &Options) {
- // Do nothing.
-}
-
-static void InitializeObjCOptions(LangOptions &Options) {
- Options.ObjC1 = Options.ObjC2 = 1;
-}
-
-
-static void InitializeLangOptions(LangOptions &Options, LangKind LK){
- // FIXME: implement -fpreprocessed mode.
- bool NoPreprocess = false;
-
- switch (LK) {
- default: assert(0 && "Unknown language kind!");
- case langkind_asm_cpp:
- Options.AsmPreprocessor = 1;
- // FALLTHROUGH
- case langkind_c_cpp:
- NoPreprocess = true;
- // FALLTHROUGH
- case langkind_c:
- InitializeCOptions(Options);
- break;
- case langkind_cxx_cpp:
- NoPreprocess = true;
- // FALLTHROUGH
- case langkind_cxx:
- Options.CPlusPlus = 1;
- break;
- case langkind_objc_cpp:
- NoPreprocess = true;
- // FALLTHROUGH
- case langkind_objc:
- InitializeObjCOptions(Options);
- break;
- case langkind_objcxx_cpp:
- NoPreprocess = true;
- // FALLTHROUGH
- case langkind_objcxx:
- Options.ObjC1 = Options.ObjC2 = 1;
- Options.CPlusPlus = 1;
- break;
- case langkind_ocl:
- Options.OpenCL = 1;
- Options.AltiVec = 1;
- Options.CXXOperatorNames = 1;
- Options.LaxVectorConversions = 1;
- break;
- }
-
- if (ObjCExclusiveGC)
- Options.setGCMode(LangOptions::GCOnly);
- else if (ObjCEnableGC)
- Options.setGCMode(LangOptions::HybridGC);
-
- if (ObjCEnableGCBitmapPrint)
- Options.ObjCGCBitmapPrint = 1;
-
- if (AltiVec)
- Options.AltiVec = 1;
-
- if (PThread)
- Options.POSIXThreads = 1;
-
- Options.setVisibilityMode(SymbolVisibility);
- Options.OverflowChecking = OverflowChecking;
-}
-
-/// LangStds - Language standards we support.
-enum LangStds {
- lang_unspecified,
- lang_c89, lang_c94, lang_c99,
- lang_gnu89, lang_gnu99,
- lang_cxx98, lang_gnucxx98,
- lang_cxx0x, lang_gnucxx0x
-};
-
-static llvm::cl::opt<LangStds>
-LangStd("std", llvm::cl::desc("Language standard to compile for"),
- llvm::cl::init(lang_unspecified),
- llvm::cl::values(clEnumValN(lang_c89, "c89", "ISO C 1990"),
- clEnumValN(lang_c89, "c90", "ISO C 1990"),
- clEnumValN(lang_c89, "iso9899:1990", "ISO C 1990"),
- clEnumValN(lang_c94, "iso9899:199409",
- "ISO C 1990 with amendment 1"),
- clEnumValN(lang_c99, "c99", "ISO C 1999"),
- clEnumValN(lang_c99, "c9x", "ISO C 1999"),
- clEnumValN(lang_c99, "iso9899:1999", "ISO C 1999"),
- clEnumValN(lang_c99, "iso9899:199x", "ISO C 1999"),
- clEnumValN(lang_gnu89, "gnu89",
- "ISO C 1990 with GNU extensions"),
- clEnumValN(lang_gnu99, "gnu99",
- "ISO C 1999 with GNU extensions (default for C)"),
- clEnumValN(lang_gnu99, "gnu9x",
- "ISO C 1999 with GNU extensions"),
- clEnumValN(lang_cxx98, "c++98",
- "ISO C++ 1998 with amendments"),
- clEnumValN(lang_gnucxx98, "gnu++98",
- "ISO C++ 1998 with amendments and GNU "
- "extensions (default for C++)"),
- clEnumValN(lang_cxx0x, "c++0x",
- "Upcoming ISO C++ 200x with amendments"),
- clEnumValN(lang_gnucxx0x, "gnu++0x",
- "Upcoming ISO C++ 200x with amendments and GNU "
- "extensions"),
- clEnumValEnd));
-
-static llvm::cl::opt<bool>
-NoOperatorNames("fno-operator-names",
- llvm::cl::desc("Do not treat C++ operator name keywords as "
- "synonyms for operators"));
-
-static llvm::cl::opt<bool>
-PascalStrings("fpascal-strings",
- llvm::cl::desc("Recognize and construct Pascal-style "
- "string literals"));
-
-static llvm::cl::opt<bool>
-MSExtensions("fms-extensions",
- llvm::cl::desc("Accept some non-standard constructs used in "
- "Microsoft header files "));
-
-static llvm::cl::opt<bool>
-WritableStrings("fwritable-strings",
- llvm::cl::desc("Store string literals as writable data"));
-
-static llvm::cl::opt<bool>
-NoLaxVectorConversions("fno-lax-vector-conversions",
- llvm::cl::desc("Disallow implicit conversions between "
- "vectors with a different number of "
- "elements or different element types"));
-
-static llvm::cl::opt<bool>
-EnableBlocks("fblocks", llvm::cl::desc("enable the 'blocks' language feature"));
-
-static llvm::cl::opt<bool>
-EnableHeinousExtensions("fheinous-gnu-extensions",
- llvm::cl::desc("enable GNU extensions that you really really shouldn't use"),
- llvm::cl::ValueDisallowed, llvm::cl::Hidden);
-
-static llvm::cl::opt<bool>
-ObjCNonFragileABI("fobjc-nonfragile-abi",
- llvm::cl::desc("enable objective-c's nonfragile abi"));
-
-
-static llvm::cl::opt<bool>
-EmitAllDecls("femit-all-decls",
- llvm::cl::desc("Emit all declarations, even if unused"));
-
-static llvm::cl::opt<bool>
-Exceptions("fexceptions",
- llvm::cl::desc("Enable support for exception handling"));
-
-static llvm::cl::opt<bool>
-Rtti("frtti", llvm::cl::init(true),
- llvm::cl::desc("Enable generation of rtti information"));
-
-static llvm::cl::opt<bool>
-GNURuntime("fgnu-runtime",
- llvm::cl::desc("Generate output compatible with the standard GNU "
- "Objective-C runtime"));
-
-static llvm::cl::opt<bool>
-NeXTRuntime("fnext-runtime",
- llvm::cl::desc("Generate output compatible with the NeXT "
- "runtime"));
-
-static llvm::cl::opt<bool>
-CharIsSigned("fsigned-char",
- llvm::cl::desc("Force char to be a signed/unsigned type"));
-
-
-static llvm::cl::opt<bool>
-Trigraphs("trigraphs", llvm::cl::desc("Process trigraph sequences"));
-
-static llvm::cl::opt<unsigned>
-TemplateDepth("ftemplate-depth", llvm::cl::init(99),
- llvm::cl::desc("Maximum depth of recursive template "
- "instantiation"));
-static llvm::cl::opt<bool>
-DollarsInIdents("fdollars-in-identifiers",
- llvm::cl::desc("Allow '$' in identifiers"));
-
-
-static llvm::cl::opt<bool>
-OptSize("Os", llvm::cl::desc("Optimize for size"));
-
-static llvm::cl::opt<bool>
-DisableLLVMOptimizations("disable-llvm-optzns",
- llvm::cl::desc("Don't run LLVM optimization passes"));
-
-static llvm::cl::opt<bool>
-NoCommon("fno-common",
- llvm::cl::desc("Compile common globals like normal definitions"),
- llvm::cl::ValueDisallowed);
-
-static llvm::cl::opt<std::string>
-MainFileName("main-file-name",
- llvm::cl::desc("Main file name to use for debug info"));
-
-// FIXME: Also add an "-fno-access-control" option.
-static llvm::cl::opt<bool>
-AccessControl("faccess-control",
- llvm::cl::desc("Enable C++ access control"));
-
-static llvm::cl::opt<bool>
-NoElideConstructors("fno-elide-constructors",
- llvm::cl::desc("Disable C++ copy constructor elision"));
-
-static llvm::cl::opt<bool>
-NoMergeConstants("fno-merge-all-constants",
- llvm::cl::desc("Disallow merging of constants."));
-
-static llvm::cl::opt<std::string>
-TargetABI("target-abi",
- llvm::cl::desc("Target a particular ABI type"));
-
-static llvm::cl::opt<std::string>
-TargetTriple("triple",
- llvm::cl::desc("Specify target triple (e.g. i686-apple-darwin9)"));
-
-
-// It might be nice to add bounds to the CommandLine library directly.
-struct OptLevelParser : public llvm::cl::parser<unsigned> {
- bool parse(llvm::cl::Option &O, llvm::StringRef ArgName,
- llvm::StringRef Arg, unsigned &Val) {
- if (llvm::cl::parser<unsigned>::parse(O, ArgName, Arg, Val))
- return true;
- if (Val > 3)
- return O.error("'" + Arg + "' invalid optimization level!");
- return false;
- }
-};
-static llvm::cl::opt<unsigned, false, OptLevelParser>
-OptLevel("O", llvm::cl::Prefix,
- llvm::cl::desc("Optimization level"),
- llvm::cl::init(0));
-
-static llvm::cl::opt<unsigned>
-PICLevel("pic-level", llvm::cl::desc("Value for __PIC__"));
-
-static llvm::cl::opt<bool>
-StaticDefine("static-define", llvm::cl::desc("Should __STATIC__ be defined"));
-
-static llvm::cl::opt<int>
-StackProtector("stack-protector",
- llvm::cl::desc("Enable stack protectors"),
- llvm::cl::init(-1));
-
-static void InitializeLanguageStandard(LangOptions &Options, LangKind LK,
- TargetInfo *Target,
- const llvm::StringMap<bool> &Features) {
- // Allow the target to set the default the langauge options as it sees fit.
- Target->getDefaultLangOptions(Options);
-
- // Pass the map of target features to the target for validation and
- // processing.
- Target->HandleTargetFeatures(Features);
-
- if (LangStd == lang_unspecified) {
- // Based on the base language, pick one.
- switch (LK) {
- case langkind_ast: assert(0 && "Invalid call for AST inputs");
- case lang_unspecified: assert(0 && "Unknown base language");
- case langkind_ocl:
- LangStd = lang_c99;
- break;
- case langkind_c:
- case langkind_asm_cpp:
- case langkind_c_cpp:
- case langkind_objc:
- case langkind_objc_cpp:
- LangStd = lang_gnu99;
- break;
- case langkind_cxx:
- case langkind_cxx_cpp:
- case langkind_objcxx:
- case langkind_objcxx_cpp:
- LangStd = lang_gnucxx98;
- break;
- }
- }
-
- switch (LangStd) {
- default: assert(0 && "Unknown language standard!");
-
- // Fall through from newer standards to older ones. This isn't really right.
- // FIXME: Enable specifically the right features based on the language stds.
- case lang_gnucxx0x:
- case lang_cxx0x:
- Options.CPlusPlus0x = 1;
- // FALL THROUGH
- case lang_gnucxx98:
- case lang_cxx98:
- Options.CPlusPlus = 1;
- Options.CXXOperatorNames = !NoOperatorNames;
- // FALL THROUGH.
- case lang_gnu99:
- case lang_c99:
- Options.C99 = 1;
- Options.HexFloats = 1;
- // FALL THROUGH.
- case lang_gnu89:
- Options.BCPLComment = 1; // Only for C99/C++.
- // FALL THROUGH.
- case lang_c94:
- Options.Digraphs = 1; // C94, C99, C++.
- // FALL THROUGH.
- case lang_c89:
- break;
- }
-
- // GNUMode - Set if we're in gnu99, gnu89, gnucxx98, etc.
- switch (LangStd) {
- default: assert(0 && "Unknown language standard!");
- case lang_gnucxx0x:
- case lang_gnucxx98:
- case lang_gnu99:
- case lang_gnu89:
- Options.GNUMode = 1;
- break;
- case lang_cxx0x:
- case lang_cxx98:
- case lang_c99:
- case lang_c94:
- case lang_c89:
- Options.GNUMode = 0;
- break;
- }
-
- if (Options.CPlusPlus) {
- Options.C99 = 0;
- Options.HexFloats = 0;
- }
-
- if (LangStd == lang_c89 || LangStd == lang_c94 || LangStd == lang_gnu89)
- Options.ImplicitInt = 1;
- else
- Options.ImplicitInt = 0;
-
- // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs
- // is specified, or -std is set to a conforming mode.
- Options.Trigraphs = !Options.GNUMode;
- if (Trigraphs.getPosition())
- Options.Trigraphs = Trigraphs; // Command line option wins if specified.
-
- // If in a conformant language mode (e.g. -std=c99) Blocks defaults to off
- // even if they are normally on for the target. In GNU modes (e.g.
- // -std=gnu99) the default for blocks depends on the target settings.
- // However, blocks are not turned off when compiling Obj-C or Obj-C++ code.
- if (!Options.ObjC1 && !Options.GNUMode)
- Options.Blocks = 0;
-
- // Default to not accepting '$' in identifiers when preprocessing assembler,
- // but do accept when preprocessing C. FIXME: these defaults are right for
- // darwin, are they right everywhere?
- Options.DollarIdents = LK != langkind_asm_cpp;
- if (DollarsInIdents.getPosition()) // Explicit setting overrides default.
- Options.DollarIdents = DollarsInIdents;
-
- if (PascalStrings.getPosition())
- Options.PascalStrings = PascalStrings;
- if (MSExtensions.getPosition())
- Options.Microsoft = MSExtensions;
- Options.WritableStrings = WritableStrings;
- if (NoLaxVectorConversions.getPosition())
- Options.LaxVectorConversions = 0;
- Options.Exceptions = Exceptions;
- Options.Rtti = Rtti;
- if (EnableBlocks.getPosition())
- Options.Blocks = EnableBlocks;
- if (CharIsSigned.getPosition())
- Options.CharIsSigned = CharIsSigned;
-
- if (!AllowBuiltins)
- Options.NoBuiltin = 1;
- if (Freestanding)
- Options.Freestanding = Options.NoBuiltin = 1;
-
- if (EnableHeinousExtensions)
- Options.HeinousExtensions = 1;
-
- if (AccessControl)
- Options.AccessControl = 1;
-
- Options.ElideConstructors = !NoElideConstructors;
-
- // OpenCL and C++ both have bool, true, false keywords.
- Options.Bool = Options.OpenCL | Options.CPlusPlus;
-
- Options.MathErrno = MathErrno;
-
- Options.InstantiationDepth = TemplateDepth;
-
- // Override the default runtime if the user requested it.
- if (NeXTRuntime)
- Options.NeXTRuntime = 1;
- else if (GNURuntime)
- Options.NeXTRuntime = 0;
-
- if (!ObjCConstantStringClass.empty())
- Options.ObjCConstantStringClass = ObjCConstantStringClass.c_str();
-
- if (ObjCNonFragileABI)
- Options.ObjCNonFragileABI = 1;
-
- if (EmitAllDecls)
- Options.EmitAllDecls = 1;
-
- // The __OPTIMIZE_SIZE__ define is tied to -Oz, which we don't
- // support.
- Options.OptimizeSize = 0;
-
- // -Os implies -O2
- if (OptSize || OptLevel)
- Options.Optimize = 1;
-
- assert(PICLevel <= 2 && "Invalid value for -pic-level");
- Options.PICLevel = PICLevel;
-
- Options.GNUInline = !Options.C99;
- // FIXME: This is affected by other options (-fno-inline).
- Options.NoInline = !OptSize && !OptLevel;
-
- Options.Static = StaticDefine;
-
- switch (StackProtector) {
- default:
- assert(StackProtector <= 2 && "Invalid value for -stack-protector");
- case -1: break;
- case 0: Options.setStackProtectorMode(LangOptions::SSPOff); break;
- case 1: Options.setStackProtectorMode(LangOptions::SSPOn); break;
- case 2: Options.setStackProtectorMode(LangOptions::SSPReq); break;
- }
-
- if (MainFileName.getPosition())
- Options.setMainFileName(MainFileName.c_str());
-}
-
-//===----------------------------------------------------------------------===//
-// SourceManager initialization.
-//===----------------------------------------------------------------------===//
-
-static bool InitializeSourceManager(Preprocessor &PP,
- const std::string &InFile) {
- // Figure out where to get and map in the main file.
- SourceManager &SourceMgr = PP.getSourceManager();
- FileManager &FileMgr = PP.getFileManager();
-
- if (EmptyInputOnly) {
- const char *EmptyStr = "";
- llvm::MemoryBuffer *SB =
- llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<empty input>");
- SourceMgr.createMainFileIDForMemBuffer(SB);
- } else if (InFile != "-") {
- const FileEntry *File = FileMgr.getFile(InFile);
- if (File) SourceMgr.createMainFileID(File, SourceLocation());
- if (SourceMgr.getMainFileID().isInvalid()) {
- PP.getDiagnostics().Report(FullSourceLoc(), diag::err_fe_error_reading)
- << InFile.c_str();
- return true;
- }
- } else {
- llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN();
-
- // If stdin was empty, SB is null. Cons up an empty memory
- // buffer now.
- if (!SB) {
- const char *EmptyStr = "";
- SB = llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<stdin>");
- }
-
- SourceMgr.createMainFileIDForMemBuffer(SB);
- if (SourceMgr.getMainFileID().isInvalid()) {
- PP.getDiagnostics().Report(FullSourceLoc(),
- diag::err_fe_error_reading_stdin);
- return true;
- }
- }
-
- return false;
-}
-
-
-//===----------------------------------------------------------------------===//
-// Preprocessor Initialization
-//===----------------------------------------------------------------------===//
-
-static llvm::cl::opt<bool>
-UndefMacros("undef", llvm::cl::value_desc("macro"),
- llvm::cl::desc("undef all system defines"));
-
-static llvm::cl::list<std::string>
-D_macros("D", llvm::cl::value_desc("macro"), llvm::cl::Prefix,
- llvm::cl::desc("Predefine the specified macro"));
-static llvm::cl::list<std::string>
-U_macros("U", llvm::cl::value_desc("macro"), llvm::cl::Prefix,
- llvm::cl::desc("Undefine the specified macro"));
-
-static llvm::cl::list<std::string>
-ImplicitIncludes("include", llvm::cl::value_desc("file"),
- llvm::cl::desc("Include file before parsing"));
-static llvm::cl::list<std::string>
-ImplicitMacroIncludes("imacros", llvm::cl::value_desc("file"),
- llvm::cl::desc("Include macros from file before parsing"));
-
-static llvm::cl::opt<std::string>
-ImplicitIncludePCH("include-pch", llvm::cl::value_desc("file"),
- llvm::cl::desc("Include precompiled header file"));
-
-static llvm::cl::opt<std::string>
-ImplicitIncludePTH("include-pth", llvm::cl::value_desc("file"),
- llvm::cl::desc("Include file before parsing"));
-
-static llvm::cl::opt<bool>
-RelocatablePCH("relocatable-pch",
- llvm::cl::desc("Whether to build a relocatable precompiled "
- "header"));
-
-//===----------------------------------------------------------------------===//
-// Preprocessor include path information.
-//===----------------------------------------------------------------------===//
-
-// This tool exports a large number of command line options to control how the
-// preprocessor searches for header files. At root, however, the Preprocessor
-// object takes a very simple interface: a list of directories to search for
-//
-// FIXME: -nostdinc++
-// FIXME: -imultilib
-//
-
-static llvm::cl::opt<bool>
-nostdinc("nostdinc", llvm::cl::desc("Disable standard #include directories"));
-
-static llvm::cl::opt<bool>
-nobuiltininc("nobuiltininc",
- llvm::cl::desc("Disable builtin #include directories"));
-
-// Various command line options. These four add directories to each chain.
-static llvm::cl::list<std::string>
-F_dirs("F", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
- llvm::cl::desc("Add directory to framework include search path"));
-static llvm::cl::list<std::string>
-I_dirs("I", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
- llvm::cl::desc("Add directory to include search path"));
-static llvm::cl::list<std::string>
-idirafter_dirs("idirafter", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
- llvm::cl::desc("Add directory to AFTER include search path"));
-static llvm::cl::list<std::string>
-iquote_dirs("iquote", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
- llvm::cl::desc("Add directory to QUOTE include search path"));
-static llvm::cl::list<std::string>
-isystem_dirs("isystem", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
- llvm::cl::desc("Add directory to SYSTEM include search path"));
-
-// These handle -iprefix/-iwithprefix/-iwithprefixbefore.
-static llvm::cl::list<std::string>
-iprefix_vals("iprefix", llvm::cl::value_desc("prefix"), llvm::cl::Prefix,
- llvm::cl::desc("Set the -iwithprefix/-iwithprefixbefore prefix"));
-static llvm::cl::list<std::string>
-iwithprefix_vals("iwithprefix", llvm::cl::value_desc("dir"), llvm::cl::Prefix,
- llvm::cl::desc("Set directory to SYSTEM include search path with prefix"));
-static llvm::cl::list<std::string>
-iwithprefixbefore_vals("iwithprefixbefore", llvm::cl::value_desc("dir"),
- llvm::cl::Prefix,
- llvm::cl::desc("Set directory to include search path with prefix"));
-
-static llvm::cl::opt<std::string>
-isysroot("isysroot", llvm::cl::value_desc("dir"), llvm::cl::init("/"),
- llvm::cl::desc("Set the system root directory (usually /)"));
-
-// Finally, implement the code that groks the options above.
-
-// Add the clang headers, which are relative to the clang binary.
-void AddClangIncludePaths(const char *Argv0, InitHeaderSearch *Init) {
- llvm::sys::Path MainExecutablePath =
- llvm::sys::Path::GetMainExecutable(Argv0,
- (void*)(intptr_t)AddClangIncludePaths);
- if (MainExecutablePath.isEmpty())
- return;
-
- MainExecutablePath.eraseComponent(); // Remove /clang from foo/bin/clang
- MainExecutablePath.eraseComponent(); // Remove /bin from foo/bin
-
- // Get foo/lib/clang/<version>/include
- MainExecutablePath.appendComponent("lib");
- MainExecutablePath.appendComponent("clang");
- MainExecutablePath.appendComponent(CLANG_VERSION_STRING);
- MainExecutablePath.appendComponent("include");
-
- // We pass true to ignore sysroot so that we *always* look for clang headers
- // relative to our executable, never relative to -isysroot.
- Init->AddPath(MainExecutablePath.c_str(), InitHeaderSearch::System,
- false, false, false, true /*ignore sysroot*/);
-}
-
-/// InitializeIncludePaths - Process the -I options and set them in the
-/// HeaderSearch object.
-void InitializeIncludePaths(const char *Argv0, HeaderSearch &Headers,
- FileManager &FM, const LangOptions &Lang,
- llvm::Triple &triple) {
- InitHeaderSearch Init(Headers, Verbose, isysroot);
-
- // Handle -I... and -F... options, walking the lists in parallel.
- unsigned Iidx = 0, Fidx = 0;
- while (Iidx < I_dirs.size() && Fidx < F_dirs.size()) {
- if (I_dirs.getPosition(Iidx) < F_dirs.getPosition(Fidx)) {
- Init.AddPath(I_dirs[Iidx], InitHeaderSearch::Angled, false, true, false);
- ++Iidx;
- } else {
- Init.AddPath(F_dirs[Fidx], InitHeaderSearch::Angled, false, true, true);
- ++Fidx;
- }
- }
-
- // Consume what's left from whatever list was longer.
- for (; Iidx != I_dirs.size(); ++Iidx)
- Init.AddPath(I_dirs[Iidx], InitHeaderSearch::Angled, false, true, false);
- for (; Fidx != F_dirs.size(); ++Fidx)
- Init.AddPath(F_dirs[Fidx], InitHeaderSearch::Angled, false, true, true);
-
- // Handle -idirafter... options.
- for (unsigned i = 0, e = idirafter_dirs.size(); i != e; ++i)
- Init.AddPath(idirafter_dirs[i], InitHeaderSearch::After,
- false, true, false);
-
- // Handle -iquote... options.
- for (unsigned i = 0, e = iquote_dirs.size(); i != e; ++i)
- Init.AddPath(iquote_dirs[i], InitHeaderSearch::Quoted, false, true, false);
-
- // Handle -isystem... options.
- for (unsigned i = 0, e = isystem_dirs.size(); i != e; ++i)
- Init.AddPath(isystem_dirs[i], InitHeaderSearch::System, false, true, false);
-
- // Walk the -iprefix/-iwithprefix/-iwithprefixbefore argument lists in
- // parallel, processing the values in order of occurance to get the right
- // prefixes.
- {
- std::string Prefix = ""; // FIXME: this isn't the correct default prefix.
- unsigned iprefix_idx = 0;
- unsigned iwithprefix_idx = 0;
- unsigned iwithprefixbefore_idx = 0;
- bool iprefix_done = iprefix_vals.empty();
- bool iwithprefix_done = iwithprefix_vals.empty();
- bool iwithprefixbefore_done = iwithprefixbefore_vals.empty();
- while (!iprefix_done || !iwithprefix_done || !iwithprefixbefore_done) {
- if (!iprefix_done &&
- (iwithprefix_done ||
- iprefix_vals.getPosition(iprefix_idx) <
- iwithprefix_vals.getPosition(iwithprefix_idx)) &&
- (iwithprefixbefore_done ||
- iprefix_vals.getPosition(iprefix_idx) <
- iwithprefixbefore_vals.getPosition(iwithprefixbefore_idx))) {
- Prefix = iprefix_vals[iprefix_idx];
- ++iprefix_idx;
- iprefix_done = iprefix_idx == iprefix_vals.size();
- } else if (!iwithprefix_done &&
- (iwithprefixbefore_done ||
- iwithprefix_vals.getPosition(iwithprefix_idx) <
- iwithprefixbefore_vals.getPosition(iwithprefixbefore_idx))) {
- Init.AddPath(Prefix+iwithprefix_vals[iwithprefix_idx],
- InitHeaderSearch::System, false, false, false);
- ++iwithprefix_idx;
- iwithprefix_done = iwithprefix_idx == iwithprefix_vals.size();
- } else {
- Init.AddPath(Prefix+iwithprefixbefore_vals[iwithprefixbefore_idx],
- InitHeaderSearch::Angled, false, false, false);
- ++iwithprefixbefore_idx;
- iwithprefixbefore_done =
- iwithprefixbefore_idx == iwithprefixbefore_vals.size();
- }
- }
- }
-
- Init.AddDefaultEnvVarPaths(Lang);
-
- if (!nobuiltininc)
- AddClangIncludePaths(Argv0, &Init);
-
- if (!nostdinc)
- Init.AddDefaultSystemIncludePaths(Lang, triple);
-
- // Now that we have collected all of the include paths, merge them all
- // together and tell the preprocessor about them.
-
- Init.Realize();
-}
-
-void InitializePreprocessorInitOptions(PreprocessorInitOptions &InitOpts) {
- // Use predefines?
- InitOpts.setUsePredefines(!UndefMacros);
-
- // Add macros from the command line.
- unsigned d = 0, D = D_macros.size();
- unsigned u = 0, U = U_macros.size();
- while (d < D || u < U) {
- if (u == U || (d < D && D_macros.getPosition(d) < U_macros.getPosition(u)))
- InitOpts.addMacroDef(D_macros[d++]);
- else
- InitOpts.addMacroUndef(U_macros[u++]);
- }
-
- // If -imacros are specified, include them now. These are processed before
- // any -include directives.
- for (unsigned i = 0, e = ImplicitMacroIncludes.size(); i != e; ++i)
- InitOpts.addMacroInclude(ImplicitMacroIncludes[i]);
-
- if (!ImplicitIncludePTH.empty() || !ImplicitIncludes.empty() ||
- (!ImplicitIncludePCH.empty() && ProgAction == PrintPreprocessedInput)) {
- // We want to add these paths to the predefines buffer in order, make a
- // temporary vector to sort by their occurrence.
- llvm::SmallVector<std::pair<unsigned, std::string*>, 8> OrderedPaths;
-
- if (!ImplicitIncludePTH.empty())
- OrderedPaths.push_back(std::make_pair(ImplicitIncludePTH.getPosition(),
- &ImplicitIncludePTH));
- if (!ImplicitIncludePCH.empty() && ProgAction == PrintPreprocessedInput)
- OrderedPaths.push_back(std::make_pair(ImplicitIncludePCH.getPosition(),
- &ImplicitIncludePCH));
- for (unsigned i = 0, e = ImplicitIncludes.size(); i != e; ++i)
- OrderedPaths.push_back(std::make_pair(ImplicitIncludes.getPosition(i),
- &ImplicitIncludes[i]));
- llvm::array_pod_sort(OrderedPaths.begin(), OrderedPaths.end());
-
-
- // Now that they are ordered by position, add to the predefines buffer.
- for (unsigned i = 0, e = OrderedPaths.size(); i != e; ++i) {
- std::string *Ptr = OrderedPaths[i].second;
- if (!ImplicitIncludes.empty() &&
- Ptr >= &ImplicitIncludes[0] &&
- Ptr <= &ImplicitIncludes[ImplicitIncludes.size()-1]) {
- InitOpts.addInclude(*Ptr, false);
- } else if (Ptr == &ImplicitIncludePTH) {
- InitOpts.addInclude(*Ptr, true);
- } else {
- // We end up here when we're producing preprocessed output and
- // we loaded a PCH file. In this case, just include the header
- // file that was used to build the precompiled header.
- assert(Ptr == &ImplicitIncludePCH);
- std::string OriginalFile = PCHReader::getOriginalSourceFile(*Ptr);
- if (!OriginalFile.empty()) {
- InitOpts.addInclude(OriginalFile, false);
- ImplicitIncludePCH.clear();
- }
- }
- }
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Preprocessor construction
+// Main driver
//===----------------------------------------------------------------------===//
-static Preprocessor *
-CreatePreprocessor(Diagnostic &Diags,const LangOptions &LangInfo,
- TargetInfo &Target, SourceManager &SourceMgr,
- HeaderSearch &HeaderInfo) {
- PTHManager *PTHMgr = 0;
- if (!TokenCache.empty() && !ImplicitIncludePTH.empty()) {
- fprintf(stderr, "error: cannot use both -token-cache and -include-pth "
- "options\n");
- exit(1);
- }
-
- // Use PTH?
- if (!TokenCache.empty() || !ImplicitIncludePTH.empty()) {
- const std::string& x = TokenCache.empty() ? ImplicitIncludePTH:TokenCache;
- PTHMgr = PTHManager::Create(x, &Diags,
- TokenCache.empty() ? Diagnostic::Error
- : Diagnostic::Warning);
- }
-
- if (Diags.hasErrorOccurred())
- exit(1);
+std::string GetBuiltinIncludePath(const char *Argv0) {
+ llvm::sys::Path P =
+ llvm::sys::Path::GetMainExecutable(Argv0,
+ (void*)(intptr_t) GetBuiltinIncludePath);
- // Create the Preprocessor.
- Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target,
- SourceMgr, HeaderInfo, PTHMgr);
+ if (!P.isEmpty()) {
+ P.eraseComponent(); // Remove /clang from foo/bin/clang
+ P.eraseComponent(); // Remove /bin from foo/bin
- // Note that this is different then passing PTHMgr to Preprocessor's ctor.
- // That argument is used as the IdentifierInfoLookup argument to
- // IdentifierTable's ctor.
- if (PTHMgr) {
- PTHMgr->setPreprocessor(PP);
- PP->setPTHManager(PTHMgr);
+ // Get foo/lib/clang/<version>/include
+ P.appendComponent("lib");
+ P.appendComponent("clang");
+ P.appendComponent(CLANG_VERSION_STRING);
+ P.appendComponent("include");
}
- PreprocessorInitOptions InitOpts;
- InitializePreprocessorInitOptions(InitOpts);
- InitializePreprocessor(*PP, InitOpts);
-
- return PP;
+ return P.str();
}
-//===----------------------------------------------------------------------===//
-// Basic Parser driver
-//===----------------------------------------------------------------------===//
+static void LLVMErrorHandler(void *UserData, const std::string &Message) {
+ Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);
-static void ParseFile(Preprocessor &PP, MinimalAction *PA) {
- Parser P(PP, *PA);
- PP.EnterMainSourceFile();
+ Diags.Report(diag::err_fe_error_backend) << Message;
- // Parsing the specified input file.
- P.ParseTranslationUnit();
- delete PA;
+ // We cannot recover from llvm errors.
+ exit(1);
}
-//===----------------------------------------------------------------------===//
-// Code generation options
-//===----------------------------------------------------------------------===//
-
-static llvm::cl::opt<bool>
-GenerateDebugInfo("g",
- llvm::cl::desc("Generate source level debug information"));
-
-static llvm::cl::opt<std::string>
-TargetCPU("mcpu",
- llvm::cl::desc("Target a specific cpu type (-mcpu=help for details)"));
-
-static llvm::cl::list<std::string>
-TargetFeatures("target-feature", llvm::cl::desc("Target specific attributes"));
-
-
-static llvm::cl::opt<bool>
-DisableRedZone("disable-red-zone",
- llvm::cl::desc("Do not emit code that uses the red zone."),
- llvm::cl::init(false));
-
-static llvm::cl::opt<bool>
-NoImplicitFloat("no-implicit-float",
- llvm::cl::desc("Don't generate implicit floating point instructions (x86-only)"),
- llvm::cl::init(false));
-
-/// ComputeTargetFeatures - Recompute the target feature list to only
-/// be the list of things that are enabled, based on the target cpu
-/// and feature list.
-static void ComputeFeatureMap(TargetInfo *Target,
- llvm::StringMap<bool> &Features) {
- assert(Features.empty() && "invalid map");
-
- // Initialize the feature map based on the target.
- Target->getDefaultFeatures(TargetCPU, Features);
+/// ClangFrontendTimer - The front-end activities should charge time to it with
+/// TimeRegion. The -ftime-report option controls whether this will do
+/// anything.
+llvm::Timer *ClangFrontendTimer = 0;
- // Apply the user specified deltas.
- for (llvm::cl::list<std::string>::iterator it = TargetFeatures.begin(),
- ie = TargetFeatures.end(); it != ie; ++it) {
- const char *Name = it->c_str();
+static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
+ using namespace clang::frontend;
- // FIXME: Don't handle errors like this.
- if (Name[0] != '-' && Name[0] != '+') {
- fprintf(stderr, "error: clang-cc: invalid target feature string: %s\n",
- Name);
- exit(1);
- }
- if (!Target->setFeatureEnabled(Features, Name + 1, (Name[0] == '+'))) {
- fprintf(stderr, "error: clang-cc: invalid target feature name: %s\n",
- Name + 1);
+ switch (CI.getFrontendOpts().ProgramAction) {
+ default:
+ llvm::llvm_unreachable("Invalid program action!");
+
+ case ASTDump: return new ASTDumpAction();
+ case ASTPrint: return new ASTPrintAction();
+ case ASTPrintXML: return new ASTPrintXMLAction();
+ case ASTView: return new ASTViewAction();
+ case DumpRawTokens: return new DumpRawTokensAction();
+ case DumpRecordLayouts: return new DumpRecordAction();
+ case DumpTokens: return new DumpTokensAction();
+ case EmitAssembly: return new EmitAssemblyAction();
+ case EmitBC: return new EmitBCAction();
+ case EmitHTML: return new HTMLPrintAction();
+ case EmitLLVM: return new EmitLLVMAction();
+ case EmitLLVMOnly: return new EmitLLVMOnlyAction();
+ case FixIt: return new FixItAction();
+ case GeneratePCH: return new GeneratePCHAction();
+ case GeneratePTH: return new GeneratePTHAction();
+ case InheritanceView: return new InheritanceViewAction();
+ case ParseNoop: return new ParseOnlyAction();
+ case ParsePrintCallbacks: return new PrintParseAction();
+ case ParseSyntaxOnly: return new SyntaxOnlyAction();
+
+ case PluginAction: {
+ if (CI.getFrontendOpts().ActionName == "help") {
+ llvm::errs() << "clang-cc plugins:\n";
+ for (FrontendPluginRegistry::iterator it =
+ FrontendPluginRegistry::begin(),
+ ie = FrontendPluginRegistry::end();
+ it != ie; ++it)
+ llvm::errs() << " " << it->getName() << " - " << it->getDesc() << "\n";
exit(1);
}
- }
-}
-
-static void InitializeCompileOptions(CompileOptions &Opts,
- const LangOptions &LangOpts,
- const llvm::StringMap<bool> &Features) {
- Opts.OptimizeSize = OptSize;
- Opts.DebugInfo = GenerateDebugInfo;
- if (DisableLLVMOptimizations) {
- Opts.OptimizationLevel = 0;
- Opts.Inlining = CompileOptions::NoInlining;
- } else {
- if (OptSize) {
- // -Os implies -O2
- Opts.OptimizationLevel = 2;
- } else {
- Opts.OptimizationLevel = OptLevel;
+ for (FrontendPluginRegistry::iterator it =
+ FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
+ it != ie; ++it) {
+ if (it->getName() == CI.getFrontendOpts().ActionName)
+ return it->instantiate();
}
- // We must always run at least the always inlining pass.
- if (Opts.OptimizationLevel > 1)
- Opts.Inlining = CompileOptions::NormalInlining;
- else
- Opts.Inlining = CompileOptions::OnlyAlwaysInlining;
- }
-
- // FIXME: There are llvm-gcc options to control these selectively.
- Opts.UnrollLoops = (Opts.OptimizationLevel > 1 && !OptSize);
- Opts.SimplifyLibCalls = !LangOpts.NoBuiltin;
-
-#ifdef NDEBUG
- Opts.VerifyModule = 0;
-#endif
-
- Opts.CPU = TargetCPU;
- Opts.Features.clear();
- for (llvm::StringMap<bool>::const_iterator it = Features.begin(),
- ie = Features.end(); it != ie; ++it) {
- // FIXME: If we are completely confident that we have the right
- // set, we only need to pass the minuses.
- std::string Name(it->second ? "+" : "-");
- Name += it->first();
- Opts.Features.push_back(Name);
- }
-
- Opts.NoCommon = NoCommon | LangOpts.CPlusPlus;
-
- // Handle -ftime-report.
- Opts.TimePasses = TimeReport;
-
- Opts.DisableRedZone = DisableRedZone;
- Opts.NoImplicitFloat = NoImplicitFloat;
-
- Opts.MergeAllConstants = !NoMergeConstants;
-}
-
-//===----------------------------------------------------------------------===//
-// Fix-It Options
-//===----------------------------------------------------------------------===//
-static llvm::cl::list<ParsedSourceLocation>
-FixItAtLocations("fixit-at", llvm::cl::value_desc("source-location"),
- llvm::cl::desc("Perform Fix-It modifications at the given source location"));
-
-//===----------------------------------------------------------------------===//
-// ObjC Rewriter Options
-//===----------------------------------------------------------------------===//
-static llvm::cl::opt<bool>
-SilenceRewriteMacroWarning("Wno-rewrite-macros", llvm::cl::init(false),
- llvm::cl::desc("Silence ObjC rewriting warnings"));
-
-//===----------------------------------------------------------------------===//
-// Warning Options
-//===----------------------------------------------------------------------===//
-
-// This gets all -W options, including -Werror, -W[no-]system-headers, etc. The
-// driver has stripped off -Wa,foo etc. The driver has also translated -W to
-// -Wextra, so we don't need to worry about it.
-static llvm::cl::list<std::string>
-OptWarnings("W", llvm::cl::Prefix, llvm::cl::ValueOptional);
-
-static llvm::cl::opt<bool> OptPedantic("pedantic");
-static llvm::cl::opt<bool> OptPedanticErrors("pedantic-errors");
-static llvm::cl::opt<bool> OptNoWarnings("w");
-
-//===----------------------------------------------------------------------===//
-// Preprocessing (-E mode) Options
-//===----------------------------------------------------------------------===//
-static llvm::cl::opt<bool>
-DisableLineMarkers("P", llvm::cl::desc("Disable linemarker output in -E mode"));
-static llvm::cl::opt<bool>
-EnableCommentOutput("C", llvm::cl::desc("Enable comment output in -E mode"));
-static llvm::cl::opt<bool>
-EnableMacroCommentOutput("CC",
- llvm::cl::desc("Enable comment output in -E mode, "
- "even from macro expansions"));
-static llvm::cl::opt<bool>
-DumpMacros("dM", llvm::cl::desc("Print macro definitions in -E mode instead of"
- " normal output"));
-static llvm::cl::opt<bool>
-DumpDefines("dD", llvm::cl::desc("Print macro definitions in -E mode in "
- "addition to normal output"));
-
-//===----------------------------------------------------------------------===//
-// Dependency file options
-//===----------------------------------------------------------------------===//
-static llvm::cl::opt<std::string>
-DependencyFile("dependency-file",
- llvm::cl::desc("Filename (or -) to write dependency output to"));
-
-static llvm::cl::opt<bool>
-DependenciesIncludeSystemHeaders("sys-header-deps",
- llvm::cl::desc("Include system headers in dependency output"));
-
-static llvm::cl::list<std::string>
-DependencyTargets("MT",
- llvm::cl::desc("Specify target for dependency"));
-
-// FIXME: Implement feature
-static llvm::cl::opt<bool>
-PhonyDependencyTarget("MP",
- llvm::cl::desc("Create phony target for each dependency "
- "(other than main file)"));
-
-//===----------------------------------------------------------------------===//
-// Analysis options
-//===----------------------------------------------------------------------===//
-
-static llvm::cl::list<Analyses>
-AnalysisList(llvm::cl::desc("Source Code Analysis - Checks and Analyses"),
-llvm::cl::values(
-#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)\
-clEnumValN(NAME, CMDFLAG, DESC),
-#include "clang/Frontend/Analyses.def"
-clEnumValEnd));
-
-static llvm::cl::opt<AnalysisStores>
-AnalysisStoreOpt("analyzer-store",
- llvm::cl::desc("Source Code Analysis - Abstract Memory Store Models"),
- llvm::cl::init(BasicStoreModel),
- llvm::cl::values(
-#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN)\
-clEnumValN(NAME##Model, CMDFLAG, DESC),
-#include "clang/Frontend/Analyses.def"
-clEnumValEnd));
-
-static llvm::cl::opt<AnalysisConstraints>
-AnalysisConstraintsOpt("analyzer-constraints",
- llvm::cl::desc("Source Code Analysis - Symbolic Constraint Engines"),
- llvm::cl::init(RangeConstraintsModel),
- llvm::cl::values(
-#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN)\
-clEnumValN(NAME##Model, CMDFLAG, DESC),
-#include "clang/Frontend/Analyses.def"
-clEnumValEnd));
-
-static llvm::cl::opt<AnalysisDiagClients>
-AnalysisDiagOpt("analyzer-output",
- llvm::cl::desc("Source Code Analysis - Output Options"),
- llvm::cl::init(PD_HTML),
- llvm::cl::values(
-#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREATE)\
-clEnumValN(PD_##NAME, CMDFLAG, DESC),
-#include "clang/Frontend/Analyses.def"
-clEnumValEnd));
-
-static llvm::cl::opt<bool>
-VisualizeEGDot("analyzer-viz-egraph-graphviz",
- llvm::cl::desc("Display exploded graph using GraphViz"));
-
-static llvm::cl::opt<bool>
-VisualizeEGUbi("analyzer-viz-egraph-ubigraph",
- llvm::cl::desc("Display exploded graph using Ubigraph"));
-
-static llvm::cl::opt<bool>
-AnalyzeAll("analyzer-opt-analyze-headers",
- llvm::cl::desc("Force the static analyzer to analyze "
- "functions defined in header files"));
-
-static llvm::cl::opt<bool>
-AnalyzerDisplayProgress("analyzer-display-progress",
- llvm::cl::desc("Emit verbose output about the analyzer's progress."));
-
-static llvm::cl::opt<bool>
-PurgeDead("analyzer-purge-dead",
- llvm::cl::init(true),
- llvm::cl::desc("Remove dead symbols, bindings, and constraints before"
- " processing a statement."));
-
-static llvm::cl::opt<bool>
-EagerlyAssume("analyzer-eagerly-assume",
- llvm::cl::init(false),
- llvm::cl::desc("Eagerly assume the truth/falseness of some "
- "symbolic constraints."));
-
-static llvm::cl::opt<std::string>
-AnalyzeSpecificFunction("analyze-function",
- llvm::cl::desc("Run analysis on specific function"));
-
-static llvm::cl::opt<bool>
-TrimGraph("trim-egraph",
- llvm::cl::desc("Only show error-related paths in the analysis graph"));
-
-static AnalyzerOptions ReadAnalyzerOptions() {
- AnalyzerOptions Opts;
- Opts.AnalysisList = AnalysisList;
- Opts.AnalysisStoreOpt = AnalysisStoreOpt;
- Opts.AnalysisConstraintsOpt = AnalysisConstraintsOpt;
- Opts.AnalysisDiagOpt = AnalysisDiagOpt;
- Opts.VisualizeEGDot = VisualizeEGDot;
- Opts.VisualizeEGUbi = VisualizeEGUbi;
- Opts.AnalyzeAll = AnalyzeAll;
- Opts.AnalyzerDisplayProgress = AnalyzerDisplayProgress;
- Opts.PurgeDead = PurgeDead;
- Opts.EagerlyAssume = EagerlyAssume;
- Opts.AnalyzeSpecificFunction = AnalyzeSpecificFunction;
- Opts.TrimGraph = TrimGraph;
- return Opts;
-}
-
-//===----------------------------------------------------------------------===//
-// -dump-build-information Stuff
-//===----------------------------------------------------------------------===//
-
-static llvm::cl::opt<std::string>
-DumpBuildInformation("dump-build-information",
- llvm::cl::value_desc("filename"),
- llvm::cl::desc("output a dump of some build information to a file"));
-
-static llvm::raw_ostream *BuildLogFile = 0;
-
-/// LoggingDiagnosticClient - This is a simple diagnostic client that forwards
-/// all diagnostics to both BuildLogFile and a chained DiagnosticClient.
-namespace {
-class LoggingDiagnosticClient : public DiagnosticClient {
- llvm::OwningPtr<DiagnosticClient> Chain1;
- llvm::OwningPtr<DiagnosticClient> Chain2;
-public:
-
- LoggingDiagnosticClient(DiagnosticClient *Normal) {
- // Output diags both where requested...
- Chain1.reset(Normal);
- // .. and to our log file.
- Chain2.reset(new TextDiagnosticPrinter(*BuildLogFile, DiagOpts));
- }
-
- virtual void BeginSourceFile(const LangOptions &LO) {
- Chain1->BeginSourceFile(LO);
- Chain2->BeginSourceFile(LO);
- }
-
- virtual void EndSourceFile() {
- Chain1->EndSourceFile();
- Chain2->EndSourceFile();
- }
-
- virtual bool IncludeInDiagnosticCounts() const {
- return Chain1->IncludeInDiagnosticCounts();
- }
-
- virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
- const DiagnosticInfo &Info) {
- Chain1->HandleDiagnostic(DiagLevel, Info);
- Chain2->HandleDiagnostic(DiagLevel, Info);
- }
-};
-} // end anonymous namespace.
-
-static void SetUpBuildDumpLog(unsigned argc, char **argv,
- llvm::OwningPtr<DiagnosticClient> &DiagClient) {
-
- std::string ErrorInfo;
- BuildLogFile = new llvm::raw_fd_ostream(DumpBuildInformation.c_str(),
- ErrorInfo);
-
- if (!ErrorInfo.empty()) {
- llvm::errs() << "error opening -dump-build-information file '"
- << DumpBuildInformation << "', option ignored!\n";
- delete BuildLogFile;
- BuildLogFile = 0;
- DumpBuildInformation = "";
- return;
- }
-
- (*BuildLogFile) << "clang-cc command line arguments: ";
- for (unsigned i = 0; i != argc; ++i)
- (*BuildLogFile) << argv[i] << ' ';
- (*BuildLogFile) << '\n';
-
- // LoggingDiagnosticClient - Insert a new logging diagnostic client in between
- // the diagnostic producers and the normal receiver.
- DiagClient.reset(new LoggingDiagnosticClient(DiagClient.take()));
-}
-
-
-
-//===----------------------------------------------------------------------===//
-// Main driver
-//===----------------------------------------------------------------------===//
-
-static llvm::raw_ostream *ComputeOutFile(const std::string &InFile,
- const char *Extension,
- bool Binary,
- llvm::sys::Path& OutPath) {
- llvm::raw_ostream *Ret;
- std::string OutFile;
- if (!OutputFile.empty())
- OutFile = OutputFile;
- else if (InFile == "-") {
- OutFile = "-";
- } else if (Extension) {
- llvm::sys::Path Path(InFile);
- Path.eraseSuffix();
- Path.appendSuffix(Extension);
- OutFile = Path.str();
- } else {
- OutFile = "-";
- }
-
- std::string Error;
- Ret = new llvm::raw_fd_ostream(OutFile.c_str(), Error,
- (Binary ? llvm::raw_fd_ostream::F_Binary : 0));
- if (!Error.empty()) {
- // FIXME: Don't fail this way.
- llvm::errs() << "ERROR: " << Error << "\n";
- ::exit(1);
- }
-
- if (OutFile != "-")
- OutPath = OutFile;
-
- return Ret;
-}
-
-static ASTConsumer *CreateConsumerAction(Preprocessor &PP,
- const std::string &InFile,
- ProgActions PA,
- llvm::OwningPtr<llvm::raw_ostream> &OS,
- llvm::sys::Path &OutPath,
- const llvm::StringMap<bool> &Features,
- llvm::LLVMContext& Context) {
- switch (PA) {
- default:
+ CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
+ << CI.getFrontendOpts().ActionName;
return 0;
-
- case ASTPrint:
- OS.reset(ComputeOutFile(InFile, 0, false, OutPath));
- return CreateASTPrinter(OS.get());
-
- case ASTPrintXML:
- OS.reset(ComputeOutFile(InFile, "xml", false, OutPath));
- return CreateASTPrinterXML(OS.get());
-
- case ASTDump:
- return CreateASTDumper();
-
- case ASTView:
- return CreateASTViewer();
-
- case PrintDeclContext:
- return CreateDeclContextPrinter();
-
- case DumpRecordLayouts:
- return CreateRecordLayoutDumper();
-
- case InheritanceView:
- return CreateInheritanceViewer(InheritanceViewCls);
-
- case EmitAssembly:
- case EmitLLVM:
- case EmitBC:
- case EmitLLVMOnly: {
- BackendAction Act;
- if (ProgAction == EmitAssembly) {
- Act = Backend_EmitAssembly;
- OS.reset(ComputeOutFile(InFile, "s", true, OutPath));
- } else if (ProgAction == EmitLLVM) {
- Act = Backend_EmitLL;
- OS.reset(ComputeOutFile(InFile, "ll", true, OutPath));
- } else if (ProgAction == EmitLLVMOnly) {
- Act = Backend_EmitNothing;
- } else {
- Act = Backend_EmitBC;
- OS.reset(ComputeOutFile(InFile, "bc", true, OutPath));
- }
-
- CompileOptions Opts;
- InitializeCompileOptions(Opts, PP.getLangOptions(), Features);
- return CreateBackendConsumer(Act, PP.getDiagnostics(), PP.getLangOptions(),
- Opts, InFile, OS.get(), Context);
}
- case RewriteObjC:
- OS.reset(ComputeOutFile(InFile, "cpp", true, OutPath));
- return CreateObjCRewriter(InFile, OS.get(), PP.getDiagnostics(),
- PP.getLangOptions(), SilenceRewriteMacroWarning);
-
- case RewriteBlocks:
- return CreateBlockRewriter(InFile, PP.getDiagnostics(),
- PP.getLangOptions());
+ case PrintDeclContext: return new DeclContextPrintAction();
+ case PrintPreprocessedInput: return new PrintPreprocessedAction();
+ case RewriteBlocks: return new RewriteBlocksAction();
+ case RewriteMacros: return new RewriteMacrosAction();
+ case RewriteObjC: return new RewriteObjCAction();
+ case RewriteTest: return new RewriteTestAction();
+ case RunAnalysis: return new AnalysisAction();
+ case RunPreprocessorOnly: return new PreprocessOnlyAction();
}
}
-/// ProcessInputFile - Process a single input file with the specified state.
-///
-static void ProcessInputFile(Preprocessor &PP, const std::string &InFile,
- ProgActions PA,
- const llvm::StringMap<bool> &Features,
- llvm::LLVMContext& Context) {
- llvm::OwningPtr<llvm::raw_ostream> OS;
- llvm::OwningPtr<ASTConsumer> Consumer;
- bool ClearSourceMgr = false;
- FixItRewriter *FixItRewrite = 0;
- bool CompleteTranslationUnit = true;
- llvm::sys::Path OutPath;
-
- switch (PA) {
- default:
- Consumer.reset(CreateConsumerAction(PP, InFile, PA, OS, OutPath,
- Features, Context));
-
- if (!Consumer.get()) {
- PP.getDiagnostics().Report(FullSourceLoc(),
- diag::err_fe_invalid_ast_action);
- return;
- }
-
- break;;
-
- case EmitHTML:
- OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
- Consumer.reset(CreateHTMLPrinter(OS.get(), PP));
- break;
-
- case RunAnalysis:
- Consumer.reset(CreateAnalysisConsumer(PP, OutputFile,
- ReadAnalyzerOptions()));
- break;
-
- case GeneratePCH:
- if (RelocatablePCH.getValue() && !isysroot.getNumOccurrences()) {
- PP.Diag(SourceLocation(), diag::err_relocatable_without_without_isysroot);
- RelocatablePCH.setValue(false);
- }
-
- OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
- if (RelocatablePCH.getValue())
- Consumer.reset(CreatePCHGenerator(PP, OS.get(), isysroot.c_str()));
- else
- Consumer.reset(CreatePCHGenerator(PP, OS.get()));
- CompleteTranslationUnit = false;
- break;
+static TargetInfo *
+ConstructCompilerInvocation(CompilerInvocation &Opts, Diagnostic &Diags,
+ const char *Argv0, bool &IsAST) {
+ // Initialize target options.
+ InitializeTargetOptions(Opts.getTargetOpts());
- case DumpRawTokens: {
- llvm::TimeRegion Timer(ClangFrontendTimer);
- SourceManager &SM = PP.getSourceManager();
- // Start lexing the specified input file.
- Lexer RawLex(SM.getMainFileID(), SM, PP.getLangOptions());
- RawLex.SetKeepWhitespaceMode(true);
-
- Token RawTok;
- RawLex.LexFromRawLexer(RawTok);
- while (RawTok.isNot(tok::eof)) {
- PP.DumpToken(RawTok, true);
- fprintf(stderr, "\n");
- RawLex.LexFromRawLexer(RawTok);
- }
- ClearSourceMgr = true;
- break;
- }
- case DumpTokens: { // Token dump mode.
- llvm::TimeRegion Timer(ClangFrontendTimer);
- Token Tok;
- // Start preprocessing the specified input file.
- PP.EnterMainSourceFile();
- do {
- PP.Lex(Tok);
- PP.DumpToken(Tok, true);
- fprintf(stderr, "\n");
- } while (Tok.isNot(tok::eof));
- ClearSourceMgr = true;
- break;
- }
- case RunPreprocessorOnly:
- break;
-
- case GeneratePTH: {
- llvm::TimeRegion Timer(ClangFrontendTimer);
- if (OutputFile.empty() || OutputFile == "-") {
- // FIXME: Don't fail this way.
- // FIXME: Verify that we can actually seek in the given file.
- llvm::errs() << "ERROR: PTH requires an seekable file for output!\n";
- ::exit(1);
- }
- OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
- CacheTokens(PP, static_cast<llvm::raw_fd_ostream*>(OS.get()));
- ClearSourceMgr = true;
- break;
- }
-
- case PrintPreprocessedInput:
- OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
- break;
-
- case ParseNoop:
- break;
-
- case ParsePrintCallbacks: {
- llvm::TimeRegion Timer(ClangFrontendTimer);
- OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
- ParseFile(PP, CreatePrintParserActionsAction(PP, OS.get()));
- ClearSourceMgr = true;
- break;
- }
-
- case ParseSyntaxOnly: { // -fsyntax-only
- llvm::TimeRegion Timer(ClangFrontendTimer);
- Consumer.reset(new ASTConsumer());
- break;
- }
-
- case RewriteMacros:
- OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
- RewriteMacrosInInput(PP, OS.get());
- ClearSourceMgr = true;
- break;
-
- case RewriteTest:
- OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
- DoRewriteTest(PP, OS.get());
- ClearSourceMgr = true;
- break;
-
- case FixIt:
- llvm::TimeRegion Timer(ClangFrontendTimer);
- Consumer.reset(new ASTConsumer());
- FixItRewrite = new FixItRewriter(PP.getDiagnostics(),
- PP.getSourceManager(),
- PP.getLangOptions());
- break;
- }
-
- if (FixItAtLocations.size() > 0) {
- // Even without the "-fixit" flag, with may have some specific
- // locations where the user has requested fixes. Process those
- // locations now.
- if (!FixItRewrite)
- FixItRewrite = new FixItRewriter(PP.getDiagnostics(),
- PP.getSourceManager(),
- PP.getLangOptions());
-
- bool AddedFixitLocation = false;
- for (unsigned Idx = 0, Last = FixItAtLocations.size();
- Idx != Last; ++Idx) {
- RequestedSourceLocation Requested;
- if (ResolveParsedLocation(FixItAtLocations[Idx],
- PP.getFileManager(), Requested)) {
- fprintf(stderr, "FIX-IT could not find file \"%s\"\n",
- FixItAtLocations[Idx].FileName.c_str());
- } else {
- FixItRewrite->addFixItLocation(Requested);
- AddedFixitLocation = true;
- }
- }
-
- if (!AddedFixitLocation) {
- // All of the fix-it locations were bad. Don't fix anything.
- delete FixItRewrite;
- FixItRewrite = 0;
- }
- }
-
- llvm::OwningPtr<ASTContext> ContextOwner;
- if (Consumer)
- ContextOwner.reset(new ASTContext(PP.getLangOptions(),
- PP.getSourceManager(),
- PP.getTargetInfo(),
- PP.getIdentifierTable(),
- PP.getSelectorTable(),
- PP.getBuiltinInfo(),
- /* FreeMemory = */ !DisableFree,
- /* size_reserve = */0));
-
- llvm::OwningPtr<PCHReader> Reader;
- llvm::OwningPtr<ExternalASTSource> Source;
-
- if (!ImplicitIncludePCH.empty()) {
- // If the user specified -isysroot, it will be used for relocatable PCH
- // files.
- const char *isysrootPCH = 0;
- if (isysroot.getNumOccurrences() != 0)
- isysrootPCH = isysroot.c_str();
-
- Reader.reset(new PCHReader(PP, ContextOwner.get(), isysrootPCH));
-
- // The user has asked us to include a precompiled header. Load
- // the precompiled header into the AST context.
- switch (Reader->ReadPCH(ImplicitIncludePCH)) {
- case PCHReader::Success: {
- // Set the predefines buffer as suggested by the PCH
- // reader. Typically, the predefines buffer will be empty.
- PP.setPredefines(Reader->getSuggestedPredefines());
-
- // 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.
- if (ContextOwner) {
- Source.reset(Reader.take());
- ContextOwner->setExternalSource(Source);
- }
- break;
- }
-
- case PCHReader::Failure:
- // Unrecoverable failure: don't even try to process the input
- // file.
- return;
-
- case PCHReader::IgnorePCH:
- // No suitable PCH file could be found. Return an error.
- return;
-
-#if 0
- // FIXME: We can recover from failed attempts to load PCH
- // files. This code will do so, if we ever want to enable it.
-
- // We delayed the initialization of builtins in the hope of
- // loading the PCH file. Since the PCH file could not be
- // loaded, initialize builtins now.
- if (ContextOwner)
- ContextOwner->InitializeBuiltins(PP.getIdentifierTable());
-#endif
- }
-
- // Finish preprocessor initialization. We do this now (rather
- // than earlier) because this initialization creates new source
- // location entries in the source manager, which must come after
- // the source location entries for the PCH file.
- if (InitializeSourceManager(PP, InFile))
- return;
- }
-
- // If we have an ASTConsumer, run the parser with it.
- if (Consumer) {
- CodeCompleteConsumer *(*CreateCodeCompleter)(Sema &, void *) = 0;
- void *CreateCodeCompleterData = 0;
+ // Get information about the target being compiled for.
+ llvm::OwningPtr<TargetInfo> Target(
+ TargetInfo::CreateTargetInfo(Diags, Opts.getTargetOpts()));
+ if (!Target)
+ return 0;
- if (!CodeCompletionAt.FileName.empty()) {
- // Tell the source manager to chop off the given file at a specific
- // line and column.
- if (const FileEntry *Entry
- = PP.getFileManager().getFile(CodeCompletionAt.FileName)) {
- // Truncate the named file at the given line/column.
- PP.getSourceManager().truncateFileAt(Entry, CodeCompletionAt.Line,
- CodeCompletionAt.Column);
+ // Initialize frontend options.
+ InitializeFrontendOptions(Opts.getFrontendOpts());
- // Set up the creation routine for code-completion.
- CreateCodeCompleter = BuildPrintingCodeCompleter;
- } else {
- PP.getDiagnostics().Report(FullSourceLoc(),
- diag::err_fe_invalid_code_complete_file)
- << CodeCompletionAt.FileName;
- }
+ // Determine the input language, we currently require all files to match.
+ FrontendOptions::InputKind IK = Opts.getFrontendOpts().Inputs[0].first;
+ for (unsigned i = 1, e = Opts.getFrontendOpts().Inputs.size(); i != e; ++i) {
+ if (Opts.getFrontendOpts().Inputs[i].first != IK) {
+ llvm::errs() << "error: cannot have multiple input files of distinct "
+ << "language kinds without -x\n";
+ return 0;
}
-
- ParseAST(PP, Consumer.get(), *ContextOwner.get(), Stats,
- CompleteTranslationUnit,
- CreateCodeCompleter, CreateCodeCompleterData);
}
- // Perform post processing actions and actions which don't use a consumer.
- switch (PA) {
- default: break;
-
- case RunPreprocessorOnly: { // Just lex as fast as we can, no output.
- llvm::TimeRegion Timer(ClangFrontendTimer);
- Token Tok;
- // Start parsing the specified input file.
- PP.EnterMainSourceFile();
- do {
- PP.Lex(Tok);
- } while (Tok.isNot(tok::eof));
- ClearSourceMgr = true;
- break;
- }
-
- case ParseNoop: {
- llvm::TimeRegion Timer(ClangFrontendTimer);
- ParseFile(PP, new MinimalAction(PP));
- ClearSourceMgr = true;
- break;
- }
-
- case PrintPreprocessedInput: {
- llvm::TimeRegion Timer(ClangFrontendTimer);
- if (DumpMacros)
- DoPrintMacros(PP, OS.get());
- else
- DoPrintPreprocessedInput(PP, OS.get(), EnableCommentOutput,
- EnableMacroCommentOutput,
- DisableLineMarkers, DumpDefines);
- ClearSourceMgr = true;
- }
-
- }
-
- if (FixItRewrite)
- FixItRewrite->WriteFixedFile(InFile, OutputFile);
-
- // Disable the consumer prior to the context, the consumer may perform actions
- // in its destructor which require the context.
- if (DisableFree)
- Consumer.take();
- else
- Consumer.reset();
-
- // If in -disable-free mode, don't deallocate ASTContext.
- if (DisableFree)
- ContextOwner.take();
- else
- ContextOwner.reset(); // Delete ASTContext
-
- if (VerifyDiagnostics)
- if (CheckDiagnostics(PP))
- exit(1);
-
- if (Stats) {
- fprintf(stderr, "\nSTATISTICS FOR '%s':\n", InFile.c_str());
- PP.PrintStats();
- PP.getIdentifierTable().PrintStats();
- PP.getHeaderSearchInfo().PrintStats();
- PP.getSourceManager().PrintStats();
- fprintf(stderr, "\n");
- }
-
- // For a multi-file compilation, some things are ok with nuking the source
- // manager tables, other require stable fileid/macroid's across multiple
- // files.
- if (ClearSourceMgr)
- PP.getSourceManager().clearIDTables();
-
- // Always delete the output stream because we don't want to leak file
- // handles. Also, we don't want to try to erase an open file.
- OS.reset();
-
- // If we had errors, try to erase the output file.
- if (PP.getDiagnostics().getNumErrors() && !OutPath.isEmpty())
- OutPath.eraseFromDisk();
-}
-
-/// ProcessInputFile - Process a single AST input file with the specified state.
-///
-static void ProcessASTInputFile(const std::string &InFile, ProgActions PA,
- const llvm::StringMap<bool> &Features,
- Diagnostic &Diags, FileManager &FileMgr,
- llvm::LLVMContext& Context) {
- std::string Error;
- llvm::OwningPtr<ASTUnit> AST(ASTUnit::LoadFromPCHFile(InFile, &Error));
- if (!AST) {
- Diags.Report(FullSourceLoc(), diag::err_fe_invalid_ast_file) << Error;
- return;
- }
-
- Preprocessor &PP = AST->getPreprocessor();
-
- llvm::OwningPtr<llvm::raw_ostream> OS;
- llvm::sys::Path OutPath;
- llvm::OwningPtr<ASTConsumer> Consumer(CreateConsumerAction(PP, InFile, PA, OS,
- OutPath, Features,
- Context));
-
- if (!Consumer.get()) {
- Diags.Report(FullSourceLoc(), diag::err_fe_invalid_ast_action);
- return;
- }
-
- // Set the main file ID to an empty file.
+ // Initialize language options.
//
- // FIXME: We probably shouldn't need this, but for now this is the simplest
- // way to reuse the logic in ParseAST.
- const char *EmptyStr = "";
- llvm::MemoryBuffer *SB =
- llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<dummy input>");
- AST->getSourceManager().createMainFileIDForMemBuffer(SB);
-
- // Stream the input AST to the consumer.
- Diags.getClient()->BeginSourceFile(PP.getLangOptions());
- ParseAST(PP, Consumer.get(), AST->getASTContext(), Stats);
- Diags.getClient()->EndSourceFile();
+ // FIXME: These aren't used during operations on ASTs. Split onto a separate
+ // code path to make this obvious.
+ IsAST = (IK == FrontendOptions::IK_AST);
+ if (!IsAST)
+ InitializeLangOptions(Opts.getLangOpts(), IK, *Target);
- // Release the consumer and the AST, in that order since the consumer may
- // perform actions in its destructor which require the context.
- if (DisableFree) {
- Consumer.take();
- AST.take();
- } else {
- Consumer.reset();
- AST.reset();
- }
+ // Initialize the static analyzer options.
+ InitializeAnalyzerOptions(Opts.getAnalyzerOpts());
- // Always delete the output stream because we don't want to leak file
- // handles. Also, we don't want to try to erase an open file.
- OS.reset();
+ // Initialize the dependency output options (-M...).
+ InitializeDependencyOutputOptions(Opts.getDependencyOutputOpts());
- // If we had errors, try to erase the output file.
- if (PP.getDiagnostics().getNumErrors() && !OutPath.isEmpty())
- OutPath.eraseFromDisk();
-}
+ // Initialize the header search options.
+ InitializeHeaderSearchOptions(Opts.getHeaderSearchOpts(),
+ GetBuiltinIncludePath(Argv0));
-static llvm::cl::list<std::string>
-InputFilenames(llvm::cl::Positional, llvm::cl::desc("<input files>"));
+ // Initialize the other preprocessor options.
+ InitializePreprocessorOptions(Opts.getPreprocessorOpts());
-static void LLVMErrorHandler(void *UserData, const std::string &Message) {
- Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);
+ // Initialize the preprocessed output options.
+ InitializePreprocessorOutputOptions(Opts.getPreprocessorOutputOpts());
- Diags.Report(FullSourceLoc(), diag::err_fe_error_backend) << Message;
+ // Initialize backend options, which may also be used to key some language
+ // options.
+ InitializeCodeGenOptions(Opts.getCodeGenOpts(), Opts.getLangOpts(),
+ Opts.getFrontendOpts().ShowTimers);
- // We cannot recover from llvm errors.
- exit(1);
+ return Target.take();
}
int main(int argc, char **argv) {
llvm::sys::PrintStackTraceOnErrorSignal();
llvm::PrettyStackTraceProgram X(argc, argv);
- llvm::LLVMContext &Context = llvm::getGlobalContext();
+ CompilerInstance Clang(&llvm::getGlobalContext(), false);
// Initialize targets first, so that --version shows registered targets.
llvm::InitializeAllTargets();
@@ -2132,183 +208,102 @@ int main(int argc, char **argv) {
llvm::cl::ParseCommandLineOptions(argc, argv,
"LLVM 'Clang' Compiler: http://clang.llvm.org\n");
- if (TimeReport)
- ClangFrontendTimer = new llvm::Timer("Clang front-end time");
-
- if (Verbose)
- llvm::errs() << "clang-cc version " CLANG_VERSION_STRING
- << " based upon " << PACKAGE_STRING
- << " hosted on " << llvm::sys::getHostTriple() << "\n";
-
- // If no input was specified, read from stdin.
- if (InputFilenames.empty())
- InputFilenames.push_back("-");
-
- // Initialize the diagnostic options.
- DiagOpts.ShowColumn = !NoShowColumn;
- DiagOpts.ShowLocation = !NoShowLocation;
- DiagOpts.ShowCarets = !NoCaretDiagnostics;
- DiagOpts.ShowFixits = !NoDiagnosticsFixIt;
- DiagOpts.ShowSourceRanges = PrintSourceRangeInfo;
- DiagOpts.ShowOptionNames = PrintDiagnosticOption;
- DiagOpts.ShowColors = PrintColorDiagnostic;
- DiagOpts.MessageLength = MessageLength;
-
- // Create the diagnostic client for reporting errors or for
- // implementing -verify.
- llvm::OwningPtr<DiagnosticClient> DiagClient;
- if (VerifyDiagnostics) {
- // When checking diagnostics, just buffer them up.
- DiagClient.reset(new TextDiagnosticBuffer());
- if (InputFilenames.size() != 1) {
- fprintf(stderr, "-verify only works on single input files for now.\n");
- return 1;
- }
- } else {
- DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), DiagOpts));
- }
-
- if (!DumpBuildInformation.empty())
- SetUpBuildDumpLog(argc, argv, DiagClient);
-
- // Configure our handling of diagnostics.
- Diagnostic Diags(DiagClient.get());
- if (ProcessWarningOptions(Diags, OptWarnings, OptPedantic, OptPedanticErrors,
- OptNoWarnings))
+ // Construct the diagnostic engine first, so that we can build a diagnostic
+ // client to use for any errors during option handling.
+ InitializeDiagnosticOptions(Clang.getDiagnosticOpts());
+ Clang.createDiagnostics(argc, argv);
+ if (!Clang.hasDiagnostics())
return 1;
// Set an error handler, so that any LLVM backend diagnostics go through our
// error handler.
llvm::llvm_install_error_handler(LLVMErrorHandler,
- static_cast<void*>(&Diags));
-
- // Initialize base triple. If a -triple option has been specified, use
- // that triple. Otherwise, default to the host triple.
- llvm::Triple Triple(TargetTriple);
- if (Triple.getTriple().empty())
- Triple = llvm::Triple(llvm::sys::getHostTriple());
+ static_cast<void*>(&Clang.getDiagnostics()));
- // Get information about the target being compiled for.
- llvm::OwningPtr<TargetInfo>
- Target(TargetInfo::CreateTargetInfo(Triple.getTriple()));
-
- if (Target == 0) {
- Diags.Report(FullSourceLoc(), diag::err_fe_unknown_triple)
- << Triple.getTriple().c_str();
+ // Now that we have initialized the diagnostics engine, create the target and
+ // the compiler invocation object.
+ //
+ // FIXME: We should move .ast inputs to taking a separate path, they are
+ // really quite different.
+ bool IsAST = false;
+ Clang.setTarget(
+ ConstructCompilerInvocation(Clang.getInvocation(), Clang.getDiagnostics(),
+ argv[0], IsAST));
+ if (!Clang.hasTarget())
return 1;
- }
-
- // Set the target ABI if specified.
- if (!TargetABI.empty()) {
- if (!Target->setABI(TargetABI)) {
- Diags.Report(FullSourceLoc(), diag::err_fe_unknown_target_abi)
- << TargetABI;
- return 1;
- }
- }
-
- if (!InheritanceViewCls.empty()) // C++ visualization?
- ProgAction = InheritanceView;
-
- // Create the source manager.
- SourceManager SourceMgr;
-
- // Create a file manager object to provide access to and cache the filesystem.
- FileManager FileMgr;
-
- // Compute the feature set, unfortunately this effects the language!
- llvm::StringMap<bool> Features;
- ComputeFeatureMap(Target.get(), Features);
-
- for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) {
- const std::string &InFile = InputFilenames[i];
-
- LangKind LK = GetLanguage(InFile);
- // AST inputs are handled specially.
- if (LK == langkind_ast) {
- ProcessASTInputFile(InFile, ProgAction, Features,
- Diags, FileMgr, Context);
- continue;
- }
-
- // Reset the ID tables if we are reusing the SourceManager.
- if (i)
- SourceMgr.clearIDTables();
-
- // Initialize language options, inferring file types from input filenames.
- LangOptions LangInfo;
- InitializeLangOptions(LangInfo, LK);
- InitializeLanguageStandard(LangInfo, LK, Target.get(), Features);
-
- // Process the -I options and set them in the HeaderInfo.
- HeaderSearch HeaderInfo(FileMgr);
-
-
- InitializeIncludePaths(argv[0], HeaderInfo, FileMgr, LangInfo, Triple);
+ // Validate/process some options
+ if (Clang.getHeaderSearchOpts().Verbose)
+ llvm::errs() << "clang-cc version " CLANG_VERSION_STRING
+ << " based upon " << PACKAGE_STRING
+ << " hosted on " << llvm::sys::getHostTriple() << "\n";
- // Set up the preprocessor with these options.
- llvm::OwningPtr<Preprocessor> PP(CreatePreprocessor(Diags, LangInfo,
- *Target, SourceMgr,
- HeaderInfo));
+ if (Clang.getFrontendOpts().ShowTimers)
+ ClangFrontendTimer = new llvm::Timer("Clang front-end time");
- // Handle generating dependencies, if requested.
- if (!DependencyFile.empty()) {
- if (DependencyTargets.empty()) {
- Diags.Report(FullSourceLoc(), diag::err_fe_dependency_file_requires_MT);
- continue;
- }
- std::string ErrStr;
- llvm::raw_ostream *DependencyOS =
- new llvm::raw_fd_ostream(DependencyFile.c_str(), ErrStr);
- if (!ErrStr.empty()) {
- Diags.Report(FullSourceLoc(), diag::err_fe_error_opening)
- << DependencyFile << ErrStr;
- continue;
+ // Enforce certain implications.
+ if (!Clang.getFrontendOpts().ViewClassInheritance.empty())
+ Clang.getFrontendOpts().ProgramAction = frontend::InheritanceView;
+ if (!Clang.getFrontendOpts().FixItLocations.empty())
+ Clang.getFrontendOpts().ProgramAction = frontend::FixIt;
+
+ for (unsigned i = 0, e = Clang.getFrontendOpts().Inputs.size(); i != e; ++i) {
+ const std::string &InFile = Clang.getFrontendOpts().Inputs[i].second;
+
+ // If we aren't using an AST file, setup the file and source managers and
+ // the preprocessor.
+ if (!IsAST) {
+ if (!i) {
+ // Create a file manager object to provide access to and cache the
+ // filesystem.
+ Clang.createFileManager();
+
+ // Create the source manager.
+ Clang.createSourceManager();
+ } else {
+ // Reset the ID tables if we are reusing the SourceManager.
+ Clang.getSourceManager().clearIDTables();
}
- AttachDependencyFileGen(PP.get(), DependencyOS, DependencyTargets,
- DependenciesIncludeSystemHeaders,
- PhonyDependencyTarget);
+ // Create the preprocessor.
+ Clang.createPreprocessor();
}
- if (ImplicitIncludePCH.empty()) {
- if (InitializeSourceManager(*PP.get(), InFile))
- continue;
+ llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(Clang));
+ if (!Act)
+ break;
- // Initialize builtin info.
- PP->getBuiltinInfo().InitializeBuiltins(PP->getIdentifierTable(),
- PP->getLangOptions().NoBuiltin);
+ Act->setCurrentTimer(ClangFrontendTimer);
+ if (Act->BeginSourceFile(Clang, InFile, IsAST)) {
+ Act->Execute();
+ Act->EndSourceFile();
}
-
- // Process the source file.
- DiagClient->BeginSourceFile(LangInfo);
- ProcessInputFile(*PP, InFile, ProgAction, Features, Context);
- DiagClient->EndSourceFile();
-
- HeaderInfo.ClearFileInfo();
}
- if (!NoCaretDiagnostics)
- if (unsigned NumDiagnostics = Diags.getNumDiagnostics())
+ if (Clang.getDiagnosticOpts().ShowCarets)
+ if (unsigned NumDiagnostics = Clang.getDiagnostics().getNumDiagnostics())
fprintf(stderr, "%d diagnostic%s generated.\n", NumDiagnostics,
(NumDiagnostics == 1 ? "" : "s"));
- if (Stats) {
- FileMgr.PrintStats();
+ if (Clang.getFrontendOpts().ShowStats) {
+ Clang.getFileManager().PrintStats();
fprintf(stderr, "\n");
}
delete ClangFrontendTimer;
- delete BuildLogFile;
- // If verifying diagnostics and we reached here, all is well.
- if (VerifyDiagnostics)
- return 0;
+ // Return the appropriate status when verifying diagnostics.
+ //
+ // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need
+ // this.
+ if (Clang.getDiagnosticOpts().VerifyDiagnostics)
+ return static_cast<VerifyDiagnosticsClient&>(
+ Clang.getDiagnosticClient()).HadErrors();
// Managed static deconstruction. Useful for making things like
// -time-passes usable.
llvm::llvm_shutdown();
- return (Diags.getNumErrors() != 0);
+ return (Clang.getDiagnostics().getNumErrors() != 0);
}
+
diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp
index 9d204ce..fb7c6cc 100644
--- a/tools/driver/driver.cpp
+++ b/tools/driver/driver.cpp
@@ -197,6 +197,16 @@ int main(int argc, const char **argv) {
llvm::sys::getHostTriple().c_str(),
"a.out", IsProduction, Diags);
+ // Check for ".*++" or ".*++-[^-]*" to determine if we are a C++
+ // compiler. This matches things like "c++", "clang++", and "clang++-1.1".
+ //
+ // Note that we intentionally want to use argv[0] here, to support "clang++"
+ // being a symlink.
+ std::string ProgName(llvm::sys::Path(argv[0]).getBasename());
+ if (llvm::StringRef(ProgName).endswith("++") ||
+ llvm::StringRef(ProgName).rsplit('-').first.endswith("++"))
+ TheDriver.CCCIsCXX = true;
+
llvm::OwningPtr<Compilation> C;
// Handle QA_OVERRIDE_GCC3_OPTIONS and CCC_ADD_ARGS, used for editing a
OpenPOWER on IntegriCloud