Date: Fri, 9 Dec 2011 18:30:43 +0000 (UTC) From: Dimitry Andric <dim@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org Subject: svn commit: r228366 - in vendor/clang/dist: bindings/python/clang bindings/python/tests/cindex include/clang/Basic include/clang/Driver include/clang/Frontend lib/Basic lib/CodeGen lib/Driver lib/F... Message-ID: <201112091830.pB9IUhbm044635@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: dim Date: Fri Dec 9 18:30:42 2011 New Revision: 228366 URL: http://svn.freebsd.org/changeset/base/228366 Log: Vendor import of clang 3.0 final release: http://llvm.org/svn/llvm-project/cfe/tags/RELEASE_30/final@145349 Added: vendor/clang/dist/test/CodeGen/pr9614.c vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.6/ vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.6.99/ vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.6.99/crtbegin.o vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.6/crtbegin.o vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.7.0/ vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.7.0/crtbegin.o vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.7.1/ vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.7.1/crtbegin.o vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.6.99/ vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.6.99/crtbegin.o vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.6.x/ vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.6.x/crtbegin.o vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.7.0/ vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.7.0/crtbegin.o vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.7.1/ vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.7.1/crtbegin.o vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing3/lib/gcc/i386-unknown-linux/4.7.98/ vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing3/lib/gcc/i386-unknown-linux/4.7.98/crtbegin.o vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/ vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/bin/ vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/bin/.keep vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/lib/ vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/ vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/ vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.98/ vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.98/crtbegin.o vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.99/ vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.99-rc5/ vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.99-rc5/crtbegin.o vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.99/crtbegin.o Modified: vendor/clang/dist/bindings/python/clang/cindex.py vendor/clang/dist/bindings/python/tests/cindex/test_type.py vendor/clang/dist/include/clang/Basic/Builtins.def vendor/clang/dist/include/clang/Driver/CC1Options.td vendor/clang/dist/include/clang/Driver/ToolChain.h vendor/clang/dist/include/clang/Frontend/HeaderSearchOptions.h vendor/clang/dist/lib/Basic/Version.cpp vendor/clang/dist/lib/CodeGen/CGObjCGNU.cpp vendor/clang/dist/lib/CodeGen/CodeGenModule.cpp vendor/clang/dist/lib/CodeGen/CodeGenModule.h vendor/clang/dist/lib/Driver/CMakeLists.txt vendor/clang/dist/lib/Driver/ToolChain.cpp vendor/clang/dist/lib/Driver/ToolChains.cpp vendor/clang/dist/lib/Driver/ToolChains.h vendor/clang/dist/lib/Driver/Tools.cpp vendor/clang/dist/lib/Frontend/CompilerInvocation.cpp vendor/clang/dist/lib/Frontend/InitHeaderSearch.cpp vendor/clang/dist/test/Analysis/iterators.cpp vendor/clang/dist/test/Analysis/security-syntax-checks.m vendor/clang/dist/test/Driver/linux-ld.c vendor/clang/dist/test/PCH/reloc.c vendor/clang/dist/test/Preprocessor/header_lookup1.c vendor/clang/dist/test/lit.cfg Modified: vendor/clang/dist/bindings/python/clang/cindex.py ============================================================================== --- vendor/clang/dist/bindings/python/clang/cindex.py Fri Dec 9 18:30:06 2011 (r228365) +++ vendor/clang/dist/bindings/python/clang/cindex.py Fri Dec 9 18:30:42 2011 (r228366) @@ -815,7 +815,7 @@ class Cursor(Structure): The Cursor class represents a reference to an element within the AST. It acts as a kind of iterator. """ - _fields_ = [("_kind_id", c_int), ("data", c_void_p * 3)] + _fields_ = [("_kind_id", c_int), ("xdata", c_int), ("data", c_void_p * 3)] def __eq__(self, other): return Cursor_eq(self, other) @@ -1019,7 +1019,7 @@ TypeKind.OBJCINTERFACE = TypeKind(108) TypeKind.OBJCOBJECTPOINTER = TypeKind(109) TypeKind.FUNCTIONNOPROTO = TypeKind(110) TypeKind.FUNCTIONPROTO = TypeKind(111) - +TypeKind.CONSTANTARRAY = TypeKind(112) class Type(Structure): """ Modified: vendor/clang/dist/bindings/python/tests/cindex/test_type.py ============================================================================== --- vendor/clang/dist/bindings/python/tests/cindex/test_type.py Fri Dec 9 18:30:06 2011 (r228365) +++ vendor/clang/dist/bindings/python/tests/cindex/test_type.py Fri Dec 9 18:30:42 2011 (r228366) @@ -74,3 +74,22 @@ def test_a_struct(): else: assert False, "Didn't find teststruct??" + + +constarrayInput=""" +struct teststruct { + void *A[2]; +}; +""" +def testConstantArray(): + index = Index.create() + tu = index.parse('t.c', unsaved_files = [('t.c',constarrayInput)]) + + for n in tu.cursor.get_children(): + if n.spelling == 'teststruct': + fields = list(n.get_children()) + assert fields[0].spelling == 'A' + assert fields[0].type.kind == TypeKind.CONSTANTARRAY + break + else: + assert False, "Didn't find teststruct??" Modified: vendor/clang/dist/include/clang/Basic/Builtins.def ============================================================================== --- vendor/clang/dist/include/clang/Basic/Builtins.def Fri Dec 9 18:30:06 2011 (r228365) +++ vendor/clang/dist/include/clang/Basic/Builtins.def Fri Dec 9 18:30:42 2011 (r228366) @@ -672,16 +672,16 @@ LIBBUILTIN(rindex, "c*cC*i", "f", LIBBUILTIN(bzero, "vv*z", "f", "strings.h", ALL_LANGUAGES) // POSIX unistd.h LIBBUILTIN(_exit, "vi", "fr", "unistd.h", ALL_LANGUAGES) -LIBBUILTIN(vfork, "iJ", "fj", "unistd.h", ALL_LANGUAGES) +LIBBUILTIN(vfork, "i", "fj", "unistd.h", ALL_LANGUAGES) // POSIX setjmp.h // In some systems setjmp is a macro that expands to _setjmp. We undefine // it here to avoid having two identical LIBBUILTIN entries. #undef setjmp LIBBUILTIN(_setjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES) -LIBBUILTIN(__sigsetjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES) +LIBBUILTIN(__sigsetjmp, "iJi", "fj", "setjmp.h", ALL_LANGUAGES) LIBBUILTIN(setjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES) -LIBBUILTIN(sigsetjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES) +LIBBUILTIN(sigsetjmp, "iJi", "fj", "setjmp.h", ALL_LANGUAGES) LIBBUILTIN(setjmp_syscall, "iJ", "fj", "setjmp.h", ALL_LANGUAGES) LIBBUILTIN(savectx, "iJ", "fj", "setjmp.h", ALL_LANGUAGES) LIBBUILTIN(qsetjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES) Modified: vendor/clang/dist/include/clang/Driver/CC1Options.td ============================================================================== --- vendor/clang/dist/include/clang/Driver/CC1Options.td Fri Dec 9 18:30:06 2011 (r228365) +++ vendor/clang/dist/include/clang/Driver/CC1Options.td Fri Dec 9 18:30:42 2011 (r228366) @@ -642,6 +642,17 @@ def isystem : JoinedOrSeparate<"-isystem def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">,MetaVarName<"<directory>">, HelpText<"Add directory to SYSTEM include search path, " "absolute paths are relative to -isysroot">; +def internal_isystem : JoinedOrSeparate<"-internal-isystem">, + MetaVarName<"<directory>">, + HelpText<"Add directory to the internal system include search path; these " + "are assumed to not be user-provided and are used to model system " + "and standard headers' paths.">; +def internal_externc_isystem : JoinedOrSeparate<"-internal-externc-isystem">, + MetaVarName<"<directory>">, + HelpText<"Add directory to the internal system include search path with " + "implicit extern \"C\" semantics; these are assumed to not be " + "user-provided and are used to model system and standard headers' " + "paths.">; def iprefix : JoinedOrSeparate<"-iprefix">, MetaVarName<"<prefix>">, HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">; def iwithprefix : JoinedOrSeparate<"-iwithprefix">, MetaVarName<"<dir>">, Modified: vendor/clang/dist/include/clang/Driver/ToolChain.h ============================================================================== --- vendor/clang/dist/include/clang/Driver/ToolChain.h Fri Dec 9 18:30:06 2011 (r228365) +++ vendor/clang/dist/include/clang/Driver/ToolChain.h Fri Dec 9 18:30:42 2011 (r228366) @@ -195,15 +195,21 @@ public: /// FIXME: this really belongs on some sort of DeploymentTarget abstraction virtual bool hasBlocksRuntime() const { return true; } + /// \brief Add the clang cc1 arguments for system include paths. + /// + /// This routine is responsible for adding the necessary cc1 arguments to + /// include headers from standard system header directories. + virtual void AddClangSystemIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const; + // GetCXXStdlibType - Determine the C++ standard library type to use with the // given compilation arguments. virtual CXXStdlibType GetCXXStdlibType(const ArgList &Args) const; /// AddClangCXXStdlibIncludeArgs - Add the clang -cc1 level arguments to set /// the include paths to use for the given C++ standard library type. - virtual void AddClangCXXStdlibIncludeArgs(const ArgList &Args, - ArgStringList &CmdArgs, - bool ObjCXXAutoRefCount) const; + virtual void AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const; /// AddCXXStdlibLibArgs - Add the system specific linker arguments to use /// for the given C++ standard library type. Modified: vendor/clang/dist/include/clang/Frontend/HeaderSearchOptions.h ============================================================================== --- vendor/clang/dist/include/clang/Frontend/HeaderSearchOptions.h Fri Dec 9 18:30:06 2011 (r228365) +++ vendor/clang/dist/include/clang/Frontend/HeaderSearchOptions.h Fri Dec 9 18:30:42 2011 (r228366) @@ -49,10 +49,24 @@ public: /// path. unsigned IgnoreSysRoot : 1; + /// \brief True if this entry is an internal search path. + /// + /// This typically indicates that users didn't directly provide it, but + /// instead it was provided by a compatibility layer for a particular + /// system. This isn't redundant with IsUserSupplied (even though perhaps + /// it should be) because that is false for user provided '-iwithprefix' + /// header search entries. + unsigned IsInternal : 1; + + /// \brief True if this entry's headers should be wrapped in extern "C". + unsigned ImplicitExternC : 1; + Entry(StringRef path, frontend::IncludeDirGroup group, - bool isUserSupplied, bool isFramework, bool ignoreSysRoot) + bool isUserSupplied, bool isFramework, bool ignoreSysRoot, + bool isInternal, bool implicitExternC) : Path(path), Group(group), IsUserSupplied(isUserSupplied), - IsFramework(isFramework), IgnoreSysRoot(ignoreSysRoot) {} + IsFramework(isFramework), IgnoreSysRoot(ignoreSysRoot), + IsInternal(isInternal), ImplicitExternC(implicitExternC) {} }; /// If non-empty, the directory to use as a "virtual system root" for include @@ -98,9 +112,10 @@ public: /// AddPath - Add the \arg Path path to the specified \arg Group list. void AddPath(StringRef Path, frontend::IncludeDirGroup Group, - bool IsUserSupplied, bool IsFramework, bool IgnoreSysRoot) { + bool IsUserSupplied, bool IsFramework, bool IgnoreSysRoot, + bool IsInternal = false, bool ImplicitExternC = false) { UserEntries.push_back(Entry(Path, Group, IsUserSupplied, IsFramework, - IgnoreSysRoot)); + IgnoreSysRoot, IsInternal, ImplicitExternC)); } }; Modified: vendor/clang/dist/lib/Basic/Version.cpp ============================================================================== --- vendor/clang/dist/lib/Basic/Version.cpp Fri Dec 9 18:30:06 2011 (r228365) +++ vendor/clang/dist/lib/Basic/Version.cpp Fri Dec 9 18:30:42 2011 (r228366) @@ -32,7 +32,7 @@ std::string getClangRepositoryPath() { // If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us // pick up a tag in an SVN export, for example. - static StringRef SVNRepository("$URL: http://llvm.org/svn/llvm-project/cfe/branches/release_30/lib/Basic/Version.cpp $"); + static StringRef SVNRepository("$URL: http://llvm.org/svn/llvm-project/cfe/tags/RELEASE_30/final/lib/Basic/Version.cpp $"); if (URL.empty()) { URL = SVNRepository.slice(SVNRepository.find(':'), SVNRepository.find("/lib/Basic")); Modified: vendor/clang/dist/lib/CodeGen/CGObjCGNU.cpp ============================================================================== --- vendor/clang/dist/lib/CodeGen/CGObjCGNU.cpp Fri Dec 9 18:30:06 2011 (r228365) +++ vendor/clang/dist/lib/CodeGen/CGObjCGNU.cpp Fri Dec 9 18:30:42 2011 (r228366) @@ -538,11 +538,12 @@ protected: llvm::Value *cmd, llvm::MDNode *node) { CGBuilderTy &Builder = CGF.Builder; - llvm::Value *imp = Builder.CreateCall2(MsgLookupFn, - EnforceType(Builder, Receiver, IdTy), - EnforceType(Builder, cmd, SelectorTy)); - cast<llvm::CallInst>(imp)->setMetadata(msgSendMDKind, node); - return imp; + llvm::Value *args[] = { + EnforceType(Builder, Receiver, IdTy), + EnforceType(Builder, cmd, SelectorTy) }; + llvm::CallSite imp = CGF.EmitCallOrInvoke(MsgLookupFn, args); + imp->setMetadata(msgSendMDKind, node); + return imp.getInstruction(); } virtual llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, llvm::Value *ObjCSuper, @@ -597,16 +598,17 @@ class CGObjCGNUstep : public CGObjCGNU { // The lookup function is guaranteed not to capture the receiver pointer. LookupFn->setDoesNotCapture(1); - llvm::CallInst *slot = - Builder.CreateCall3(LookupFn, - EnforceType(Builder, ReceiverPtr, PtrToIdTy), - EnforceType(Builder, cmd, SelectorTy), - EnforceType(Builder, self, IdTy)); - slot->setOnlyReadsMemory(); + llvm::Value *args[] = { + EnforceType(Builder, ReceiverPtr, PtrToIdTy), + EnforceType(Builder, cmd, SelectorTy), + EnforceType(Builder, self, IdTy) }; + llvm::CallSite slot = CGF.EmitCallOrInvoke(LookupFn, args); + slot.setOnlyReadsMemory(); slot->setMetadata(msgSendMDKind, node); // Load the imp from the slot - llvm::Value *imp = Builder.CreateLoad(Builder.CreateStructGEP(slot, 4)); + llvm::Value *imp = + Builder.CreateLoad(Builder.CreateStructGEP(slot.getInstruction(), 4)); // The lookup function may have changed the receiver, so make sure we use // the new one. @@ -1361,8 +1363,8 @@ llvm::Constant *CGObjCGNU::GenerateClass LongTy, // abi_version IvarOffsets->getType(), // ivar_offsets Properties->getType(), // properties - Int64Ty, // strong_pointers - Int64Ty, // weak_pointers + IntPtrTy, // strong_pointers + IntPtrTy, // weak_pointers NULL); llvm::Constant *Zero = llvm::ConstantInt::get(LongTy, 0); // Fill in the structure @@ -1723,12 +1725,14 @@ void CGObjCGNU::GenerateProtocolHolderCa /// bitfield / with the 63rd bit set will be 1<<64. llvm::Constant *CGObjCGNU::MakeBitField(llvm::SmallVectorImpl<bool> &bits) { int bitCount = bits.size(); - if (bitCount < 64) { + int ptrBits = + (TheModule.getPointerSize() == llvm::Module::Pointer32) ? 32 : 64; + if (bitCount < ptrBits) { uint64_t val = 1; for (int i=0 ; i<bitCount ; ++i) { if (bits[i]) val |= 1ULL<<(i+1); } - return llvm::ConstantInt::get(Int64Ty, val); + return llvm::ConstantInt::get(IntPtrTy, val); } llvm::SmallVector<llvm::Constant*, 8> values; int v=0; @@ -1748,8 +1752,6 @@ llvm::Constant *CGObjCGNU::MakeBitField( llvm::Constant *GS = MakeGlobal(llvm::StructType::get(Int32Ty, arrayTy, NULL), fields); llvm::Constant *ptr = llvm::ConstantExpr::getPtrToInt(GS, IntPtrTy); - if (IntPtrTy != Int64Ty) - ptr = llvm::ConstantExpr::getZExt(ptr, Int64Ty); return ptr; } @@ -2073,12 +2075,12 @@ void CGObjCGNU::GenerateClass(const ObjC } ++ivarIndex; } - llvm::Constant *Zero64 = llvm::ConstantInt::get(Int64Ty, 0); + llvm::Constant *ZeroPtr = llvm::ConstantInt::get(IntPtrTy, 0); //Generate metaclass for class methods llvm::Constant *MetaClassStruct = GenerateClassStructure(NULLPtr, NULLPtr, 0x12L, ClassName.c_str(), 0, Zeros[0], GenerateIvarList( empty, empty, empty), ClassMethodList, NULLPtr, - NULLPtr, NULLPtr, Zero64, Zero64, true); + NULLPtr, NULLPtr, ZeroPtr, ZeroPtr, true); // Generate the class structure llvm::Constant *ClassStruct = Modified: vendor/clang/dist/lib/CodeGen/CodeGenModule.cpp ============================================================================== --- vendor/clang/dist/lib/CodeGen/CodeGenModule.cpp Fri Dec 9 18:30:06 2011 (r228365) +++ vendor/clang/dist/lib/CodeGen/CodeGenModule.cpp Fri Dec 9 18:30:42 2011 (r228366) @@ -29,6 +29,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Mangle.h" #include "clang/AST/RecordLayout.h" +#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -858,6 +859,59 @@ void CodeGenModule::EmitGlobal(GlobalDec } } +namespace { + struct FunctionIsDirectlyRecursive : + public RecursiveASTVisitor<FunctionIsDirectlyRecursive> { + const StringRef Name; + bool Result; + FunctionIsDirectlyRecursive(const FunctionDecl *F) : + Name(F->getName()), Result(false) { + } + typedef RecursiveASTVisitor<FunctionIsDirectlyRecursive> Base; + + bool TraverseCallExpr(CallExpr *E) { + const Decl *D = E->getCalleeDecl(); + if (!D) + return true; + AsmLabelAttr *Attr = D->getAttr<AsmLabelAttr>(); + if (!Attr) + return true; + if (Name == Attr->getLabel()) { + Result = true; + return false; + } + return true; + } + }; +} + +// isTriviallyRecursiveViaAsm - Check if this function calls another +// decl that, because of the asm attribute, ends up pointing to itself. +bool +CodeGenModule::isTriviallyRecursiveViaAsm(const FunctionDecl *F) { + if (getCXXABI().getMangleContext().shouldMangleDeclName(F)) + return false; + + FunctionIsDirectlyRecursive Walker(F); + Walker.TraverseFunctionDecl(const_cast<FunctionDecl*>(F)); + return Walker.Result; +} + +bool +CodeGenModule::shouldEmitFunction(const FunctionDecl *F) { + if (getFunctionLinkage(F) != llvm::Function::AvailableExternallyLinkage) + return true; + if (CodeGenOpts.OptimizationLevel == 0 && + !F->hasAttr<AlwaysInlineAttr>()) + return false; + // PR9614. Avoid cases where the source code is lying to us. An available + // externally function should have an equivalent function somewhere else, + // but a function that calls itself is clearly not equivalent to the real + // implementation. + // This happens in glibc's btowc and in some configure checks. + return !isTriviallyRecursiveViaAsm(F); +} + void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) { const ValueDecl *D = cast<ValueDecl>(GD.getDecl()); @@ -868,10 +922,7 @@ void CodeGenModule::EmitGlobalDefinition if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { // At -O0, don't generate IR for functions with available_externally // linkage. - if (CodeGenOpts.OptimizationLevel == 0 && - !Function->hasAttr<AlwaysInlineAttr>() && - getFunctionLinkage(Function) - == llvm::Function::AvailableExternallyLinkage) + if (!shouldEmitFunction(Function)) return; if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { Modified: vendor/clang/dist/lib/CodeGen/CodeGenModule.h ============================================================================== --- vendor/clang/dist/lib/CodeGen/CodeGenModule.h Fri Dec 9 18:30:06 2011 (r228365) +++ vendor/clang/dist/lib/CodeGen/CodeGenModule.h Fri Dec 9 18:30:42 2011 (r228366) @@ -324,6 +324,8 @@ class CodeGenModule : public CodeGenType void createOpenCLRuntime(); void createCUDARuntime(); + bool isTriviallyRecursiveViaAsm(const FunctionDecl *F); + bool shouldEmitFunction(const FunctionDecl *F); llvm::LLVMContext &VMContext; /// @name Cache for Blocks Runtime Globals Modified: vendor/clang/dist/lib/Driver/CMakeLists.txt ============================================================================== --- vendor/clang/dist/lib/Driver/CMakeLists.txt Fri Dec 9 18:30:06 2011 (r228365) +++ vendor/clang/dist/lib/Driver/CMakeLists.txt Fri Dec 9 18:30:42 2011 (r228366) @@ -21,5 +21,13 @@ add_clang_library(clangDriver Types.cpp ) +IF(MSVC) + get_target_property(NON_ANSI_COMPILE_FLAGS clangDriver COMPILE_FLAGS) + string(REPLACE /Za + "" NON_ANSI_COMPILE_FLAGS + ${NON_ANSI_COMPILE_FLAGS}) + set_target_properties(clangDriver PROPERTIES COMPILE_FLAGS ${NON_ANSI_COMPILE_FLAGS}) +ENDIF(MSVC) + add_dependencies(clangDriver ClangAttrList ClangDiagnosticDriver ClangDriverOptions ClangCC1Options ClangCC1AsOptions) Modified: vendor/clang/dist/lib/Driver/ToolChain.cpp ============================================================================== --- vendor/clang/dist/lib/Driver/ToolChain.cpp Fri Dec 9 18:30:06 2011 (r228365) +++ vendor/clang/dist/lib/Driver/ToolChain.cpp Fri Dec 9 18:30:42 2011 (r228366) @@ -211,6 +211,11 @@ std::string ToolChain::ComputeEffectiveC return ComputeLLVMTriple(Args, InputType); } +void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + // Each toolchain should provide the appropriate include flags. +} + ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{ if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { StringRef Value = A->getValue(Args); @@ -225,24 +230,18 @@ ToolChain::CXXStdlibType ToolChain::GetC return ToolChain::CST_Libstdcxx; } -void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &Args, - ArgStringList &CmdArgs, - bool ObjCXXAutoRefCount) const { - CXXStdlibType Type = GetCXXStdlibType(Args); - - // Header search paths are handled by the mass of goop in InitHeaderSearch. - - switch (Type) { - case ToolChain::CST_Libcxx: - if (ObjCXXAutoRefCount) - CmdArgs.push_back("-fobjc-arc-cxxlib=libc++"); - break; - - case ToolChain::CST_Libstdcxx: - if (ObjCXXAutoRefCount) - CmdArgs.push_back("-fobjc-arc-cxxlib=libstdc++"); - break; - } +void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + // Header search paths should be handled by each of the subclasses. + // Historically, they have not been, and instead have been handled inside of + // the CC1-layer frontend. As the logic is hoisted out, this generic function + // will slowly stop being called. + // + // While it is being called, replicate a bit of a hack to propagate the + // '-stdlib=' flag down to CC1 so that it can in turn customize the C++ + // header search paths with it. Once all systems are overriding this + // function, the CC1 flag and this line can be removed. + DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ); } void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args, Modified: vendor/clang/dist/lib/Driver/ToolChains.cpp ============================================================================== --- vendor/clang/dist/lib/Driver/ToolChains.cpp Fri Dec 9 18:30:06 2011 (r228365) +++ vendor/clang/dist/lib/Driver/ToolChains.cpp Fri Dec 9 18:30:42 2011 (r228366) @@ -40,10 +40,51 @@ #include "llvm/Config/config.h" // for CXX_INCLUDE_ROOT +// Include the necessary headers to interface with the Windows registry and +// environment. +#ifdef _MSC_VER + #define WIN32_LEAN_AND_MEAN 1 + #include <Windows.h> + #undef min + #undef max +#endif + using namespace clang::driver; using namespace clang::driver::toolchains; using namespace clang; +/// \brief Utility function to add a system include directory to CC1 arguments. +static void addSystemInclude(const ArgList &DriverArgs, ArgStringList &CC1Args, + const Twine &Path) { + CC1Args.push_back("-internal-isystem"); + CC1Args.push_back(DriverArgs.MakeArgString(Path)); +} + +/// \brief Utility function to add a system include directory with extern "C" +/// semantics to CC1 arguments. +/// +/// Note that this should be used rarely, and only for directories that +/// historically and for legacy reasons are treated as having implicit extern +/// "C" semantics. These semantics are *ignored* by and large today, but its +/// important to preserve the preprocessor changes resulting from the +/// classification. +static void addExternCSystemInclude(const ArgList &DriverArgs, + ArgStringList &CC1Args, const Twine &Path) { + CC1Args.push_back("-internal-externc-isystem"); + CC1Args.push_back(DriverArgs.MakeArgString(Path)); +} + +/// \brief Utility function to add a list of system include directories to CC1. +static void addSystemIncludes(const ArgList &DriverArgs, + ArgStringList &CC1Args, + ArrayRef<StringRef> Paths) { + for (ArrayRef<StringRef>::iterator I = Paths.begin(), E = Paths.end(); + I != E; ++I) { + CC1Args.push_back("-internal-isystem"); + CC1Args.push_back(DriverArgs.MakeArgString(*I)); + } +} + /// Darwin - Darwin tool chain for i386 and x86_64. Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple) @@ -1385,19 +1426,6 @@ static bool IsUbuntu(enum LinuxDistro Di Distro == UbuntuNatty || Distro == UbuntuOneiric; } -// FIXME: This should be deleted. We should assume a multilib environment, and -// fallback gracefully if any parts of it are absent. -static bool HasMultilib(llvm::Triple::ArchType Arch, enum LinuxDistro Distro) { - if (Arch == llvm::Triple::x86_64) { - bool Exists; - if (Distro == Exherbo && - (llvm::sys::fs::exists("/usr/lib32/libc.so", Exists) || !Exists)) - return false; - } - - return true; -} - static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) { llvm::OwningPtr<llvm::MemoryBuffer> File; if (!llvm::MemoryBuffer::getFile("/etc/lsb-release", File)) { @@ -1482,280 +1510,293 @@ static LinuxDistro DetectLinuxDistro(llv return UnknownDistro; } -/// \brief Trivial helper function to simplify code checking path existence. -static bool PathExists(StringRef Path) { - bool Exists; - if (!llvm::sys::fs::exists(Path, Exists)) - return Exists; - return false; +/// \brief Parse a GCCVersion object out of a string of text. +/// +/// This is the primary means of forming GCCVersion objects. +/*static*/ Linux::GCCVersion Linux::GCCVersion::Parse(StringRef VersionText) { + const GCCVersion BadVersion = { VersionText.str(), -1, -1, -1, "" }; + std::pair<StringRef, StringRef> First = VersionText.split('.'); + std::pair<StringRef, StringRef> Second = First.second.split('.'); + + GCCVersion GoodVersion = { VersionText.str(), -1, -1, -1, "" }; + if (First.first.getAsInteger(10, GoodVersion.Major) || + GoodVersion.Major < 0) + return BadVersion; + if (Second.first.getAsInteger(10, GoodVersion.Minor) || + GoodVersion.Minor < 0) + return BadVersion; + + // First look for a number prefix and parse that if present. Otherwise just + // stash the entire patch string in the suffix, and leave the number + // unspecified. This covers versions strings such as: + // 4.4 + // 4.4.0 + // 4.4.x + // 4.4.2-rc4 + // 4.4.x-patched + // And retains any patch number it finds. + StringRef PatchText = GoodVersion.PatchSuffix = Second.second.str(); + if (!PatchText.empty()) { + if (unsigned EndNumber = PatchText.find_first_not_of("0123456789")) { + // Try to parse the number and any suffix. + if (PatchText.slice(0, EndNumber).getAsInteger(10, GoodVersion.Patch) || + GoodVersion.Patch < 0) + return BadVersion; + GoodVersion.PatchSuffix = PatchText.substr(EndNumber).str(); + } + } + + return GoodVersion; } -namespace { -/// \brief This is a class to find a viable GCC installation for Clang to use. -/// -/// This class tries to find a GCC installation on the system, and report -/// information about it. It starts from the host information provided to the -/// Driver, and has logic for fuzzing that where appropriate. -class GCCInstallationDetector { - /// \brief Struct to store and manipulate GCC versions. - /// - /// We rely on assumptions about the form and structure of GCC version - /// numbers: they consist of at most three '.'-separated components, and each - /// component is a non-negative integer. - struct GCCVersion { - unsigned Major, Minor, Patch; - - static GCCVersion Parse(StringRef VersionText) { - const GCCVersion BadVersion = {0, 0, 0}; - std::pair<StringRef, StringRef> First = VersionText.split('.'); - std::pair<StringRef, StringRef> Second = First.second.split('.'); +/// \brief Less-than for GCCVersion, implementing a Strict Weak Ordering. +bool Linux::GCCVersion::operator<(const GCCVersion &RHS) const { + if (Major < RHS.Major) return true; if (Major > RHS.Major) return false; + if (Minor < RHS.Minor) return true; if (Minor > RHS.Minor) return false; - GCCVersion GoodVersion = {0, 0, 0}; - if (First.first.getAsInteger(10, GoodVersion.Major)) - return BadVersion; - if (Second.first.getAsInteger(10, GoodVersion.Minor)) - return BadVersion; - // We accept a number, or a string for the patch version, in case there - // is a strang suffix, or other mangling: '4.1.x', '4.1.2-rc3'. When it - // isn't a number, we just use '0' as the number but accept it. - if (Second.first.getAsInteger(10, GoodVersion.Patch)) - GoodVersion.Patch = 0; - return GoodVersion; - } - - bool operator<(const GCCVersion &RHS) const { - if (Major < RHS.Major) return true; - if (Major > RHS.Major) return false; - if (Minor < RHS.Minor) return true; - if (Minor > RHS.Minor) return false; - return Patch < RHS.Patch; - } - bool operator>(const GCCVersion &RHS) const { return RHS < *this; } - bool operator<=(const GCCVersion &RHS) const { return !(*this > RHS); } - bool operator>=(const GCCVersion &RHS) const { return !(*this < RHS); } - }; + // Note that we rank versions with *no* patch specified is better than ones + // hard-coding a patch version. Thus if the RHS has no patch, it always + // wins, and the LHS only wins if it has no patch and the RHS does have + // a patch. + if (RHS.Patch == -1) return true; if (Patch == -1) return false; + if (Patch < RHS.Patch) return true; if (Patch > RHS.Patch) return false; - bool IsValid; - std::string GccTriple; + // Finally, between completely tied version numbers, the version with the + // suffix loses as we prefer full releases. + if (RHS.PatchSuffix.empty()) return true; + return false; +} - // FIXME: These might be better as path objects. - std::string GccInstallPath; - std::string GccParentLibPath; - - llvm::SmallString<128> CxxIncludeRoot; - -public: - /// \brief Construct a GCCInstallationDetector from the driver. - /// - /// This performs all of the autodetection and sets up the various paths. - /// Once constructed, a GCCInstallation is esentially immutable. - GCCInstallationDetector(const Driver &D) - : IsValid(false), - GccTriple(D.DefaultHostTriple), - CxxIncludeRoot(CXX_INCLUDE_ROOT) { - // FIXME: Using CXX_INCLUDE_ROOT is here is a bit of a hack, but - // avoids adding yet another option to configure/cmake. - // It would probably be cleaner to break it in two variables - // CXX_GCC_ROOT with just /foo/bar - // CXX_GCC_VER with 4.5.2 - // Then we would have - // CXX_INCLUDE_ROOT = CXX_GCC_ROOT/include/c++/CXX_GCC_VER - // and this function would return - // CXX_GCC_ROOT/lib/gcc/CXX_INCLUDE_ARCH/CXX_GCC_VER - if (CxxIncludeRoot != "") { - // This is of the form /foo/bar/include/c++/4.5.2/ - if (CxxIncludeRoot.back() == '/') - llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the / - StringRef Version = llvm::sys::path::filename(CxxIncludeRoot); - llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the version - llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the c++ - llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the include - GccInstallPath = CxxIncludeRoot.str(); - GccInstallPath.append("/lib/gcc/"); - GccInstallPath.append(CXX_INCLUDE_ARCH); - GccInstallPath.append("/"); - GccInstallPath.append(Version); - GccParentLibPath = GccInstallPath + "/../../.."; - IsValid = true; - return; - } +/// \brief Construct a GCCInstallationDetector from the driver. +/// +/// This performs all of the autodetection and sets up the various paths. +/// Once constructed, a GCCInstallation is esentially immutable. +Linux::GCCInstallationDetector::GCCInstallationDetector(const Driver &D) + : IsValid(false), + GccTriple(D.DefaultHostTriple) { + // FIXME: Using CXX_INCLUDE_ROOT is here is a bit of a hack, but + // avoids adding yet another option to configure/cmake. + // It would probably be cleaner to break it in two variables + // CXX_GCC_ROOT with just /foo/bar + // CXX_GCC_VER with 4.5.2 + // Then we would have + // CXX_INCLUDE_ROOT = CXX_GCC_ROOT/include/c++/CXX_GCC_VER + // and this function would return + // CXX_GCC_ROOT/lib/gcc/CXX_INCLUDE_ARCH/CXX_GCC_VER + llvm::SmallString<128> CxxIncludeRoot(CXX_INCLUDE_ROOT); + if (CxxIncludeRoot != "") { + // This is of the form /foo/bar/include/c++/4.5.2/ + if (CxxIncludeRoot.back() == '/') + llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the / + StringRef Version = llvm::sys::path::filename(CxxIncludeRoot); + llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the version + llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the c++ + llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the include + GccInstallPath = CxxIncludeRoot.str(); + GccInstallPath.append("/lib/gcc/"); + GccInstallPath.append(CXX_INCLUDE_ARCH); + GccInstallPath.append("/"); + GccInstallPath.append(Version); + GccParentLibPath = GccInstallPath + "/../../.."; + IsValid = true; + return; + } - llvm::Triple::ArchType HostArch = llvm::Triple(GccTriple).getArch(); - // The library directories which may contain GCC installations. - SmallVector<StringRef, 4> CandidateLibDirs; - // The compatible GCC triples for this particular architecture. - SmallVector<StringRef, 10> CandidateTriples; - CollectLibDirsAndTriples(HostArch, CandidateLibDirs, CandidateTriples); - - // Always include the default host triple as the final fallback if no - // specific triple is detected. - CandidateTriples.push_back(D.DefaultHostTriple); - - // Compute the set of prefixes for our search. - SmallVector<std::string, 8> Prefixes(D.PrefixDirs.begin(), - D.PrefixDirs.end()); - Prefixes.push_back(D.SysRoot); - Prefixes.push_back(D.SysRoot + "/usr"); - Prefixes.push_back(D.InstalledDir + "/.."); - - // Loop over the various components which exist and select the best GCC - // installation available. GCC installs are ranked by version number. - GCCVersion BestVersion = {0, 0, 0}; - for (unsigned i = 0, ie = Prefixes.size(); i < ie; ++i) { - if (!PathExists(Prefixes[i])) + llvm::Triple::ArchType HostArch = llvm::Triple(GccTriple).getArch(); + // The library directories which may contain GCC installations. + SmallVector<StringRef, 4> CandidateLibDirs; + // The compatible GCC triples for this particular architecture. + SmallVector<StringRef, 10> CandidateTriples; + CollectLibDirsAndTriples(HostArch, CandidateLibDirs, CandidateTriples); + + // Always include the default host triple as the final fallback if no + // specific triple is detected. + CandidateTriples.push_back(D.DefaultHostTriple); + + // Compute the set of prefixes for our search. + SmallVector<std::string, 8> Prefixes(D.PrefixDirs.begin(), + D.PrefixDirs.end()); + Prefixes.push_back(D.SysRoot); + Prefixes.push_back(D.SysRoot + "/usr"); + Prefixes.push_back(D.InstalledDir + "/.."); + + // Loop over the various components which exist and select the best GCC + // installation available. GCC installs are ranked by version number. + Version = GCCVersion::Parse("0.0.0"); + for (unsigned i = 0, ie = Prefixes.size(); i < ie; ++i) { + if (!llvm::sys::fs::exists(Prefixes[i])) + continue; + for (unsigned j = 0, je = CandidateLibDirs.size(); j < je; ++j) { + const std::string LibDir = Prefixes[i] + CandidateLibDirs[j].str(); + if (!llvm::sys::fs::exists(LibDir)) continue; - for (unsigned j = 0, je = CandidateLibDirs.size(); j < je; ++j) { - const std::string LibDir = Prefixes[i] + CandidateLibDirs[j].str(); - if (!PathExists(LibDir)) - continue; - for (unsigned k = 0, ke = CandidateTriples.size(); k < ke; ++k) - ScanLibDirForGCCTriple(LibDir, CandidateTriples[k], BestVersion); - } + for (unsigned k = 0, ke = CandidateTriples.size(); k < ke; ++k) + ScanLibDirForGCCTriple(HostArch, LibDir, CandidateTriples[k]); } } +} - /// \brief Check whether we detected a valid GCC install. - bool isValid() const { return IsValid; } - - /// \brief Get the GCC triple for the detected install. - const std::string &getTriple() const { return GccTriple; } - - /// \brief Get the detected GCC installation path. - const std::string &getInstallPath() const { return GccInstallPath; } - - /// \brief Get the detected GCC parent lib path. - const std::string &getParentLibPath() const { return GccParentLibPath; } - -private: - static void CollectLibDirsAndTriples(llvm::Triple::ArchType HostArch, - SmallVectorImpl<StringRef> &LibDirs, - SmallVectorImpl<StringRef> &Triples) { - if (HostArch == llvm::Triple::arm || HostArch == llvm::Triple::thumb) { - static const char *const ARMLibDirs[] = { "/lib" }; - static const char *const ARMTriples[] = { "arm-linux-gnueabi" }; - LibDirs.append(ARMLibDirs, ARMLibDirs + llvm::array_lengthof(ARMLibDirs)); - Triples.append(ARMTriples, ARMTriples + llvm::array_lengthof(ARMTriples)); - } else if (HostArch == llvm::Triple::x86_64) { - static const char *const X86_64LibDirs[] = { "/lib64", "/lib" }; - static const char *const X86_64Triples[] = { - "x86_64-linux-gnu", - "x86_64-unknown-linux-gnu", - "x86_64-pc-linux-gnu", - "x86_64-redhat-linux6E", - "x86_64-redhat-linux", - "x86_64-suse-linux", - "x86_64-manbo-linux-gnu", - "x86_64-linux-gnu", - "x86_64-slackware-linux" - }; - LibDirs.append(X86_64LibDirs, - X86_64LibDirs + llvm::array_lengthof(X86_64LibDirs)); - Triples.append(X86_64Triples, - X86_64Triples + llvm::array_lengthof(X86_64Triples)); - } else if (HostArch == llvm::Triple::x86) { - static const char *const X86LibDirs[] = { "/lib32", "/lib" }; - static const char *const X86Triples[] = { - "i686-linux-gnu", - "i386-linux-gnu", - "i686-pc-linux-gnu", - "i486-linux-gnu", - "i686-redhat-linux", - "i386-redhat-linux", - "i586-suse-linux", - "i486-slackware-linux" - }; - LibDirs.append(X86LibDirs, X86LibDirs + llvm::array_lengthof(X86LibDirs)); - Triples.append(X86Triples, X86Triples + llvm::array_lengthof(X86Triples)); - } else if (HostArch == llvm::Triple::ppc) { - static const char *const PPCLibDirs[] = { "/lib32", "/lib" }; - static const char *const PPCTriples[] = { - "powerpc-linux-gnu", - "powerpc-unknown-linux-gnu" - }; - LibDirs.append(PPCLibDirs, PPCLibDirs + llvm::array_lengthof(PPCLibDirs)); - Triples.append(PPCTriples, PPCTriples + llvm::array_lengthof(PPCTriples)); - } else if (HostArch == llvm::Triple::ppc64) { - static const char *const PPC64LibDirs[] = { "/lib64", "/lib" }; - static const char *const PPC64Triples[] = { - "powerpc64-unknown-linux-gnu" - }; - LibDirs.append(PPC64LibDirs, - PPC64LibDirs + llvm::array_lengthof(PPC64LibDirs)); - Triples.append(PPC64Triples, - PPC64Triples + llvm::array_lengthof(PPC64Triples)); - } - } - - void ScanLibDirForGCCTriple(const std::string &LibDir, - StringRef CandidateTriple, - GCCVersion &BestVersion) { - // There are various different suffixes involving the triple we - // check for. We also record what is necessary to walk from each back - // up to the lib directory. - const std::string Suffixes[] = { - "/gcc/" + CandidateTriple.str(), - "/" + CandidateTriple.str() + "/gcc/" + CandidateTriple.str(), - - // Ubuntu has a strange mis-matched pair of triples that this happens to - // match. - // FIXME: It may be worthwhile to generalize this and look for a second - // triple. - "/" + CandidateTriple.str() + "/gcc/i686-linux-gnu" +/*static*/ void Linux::GCCInstallationDetector::CollectLibDirsAndTriples( + llvm::Triple::ArchType HostArch, SmallVectorImpl<StringRef> &LibDirs, + SmallVectorImpl<StringRef> &Triples) { + if (HostArch == llvm::Triple::arm || HostArch == llvm::Triple::thumb) { + static const char *const ARMLibDirs[] = { "/lib" }; + static const char *const ARMTriples[] = { "arm-linux-gnueabi" }; + LibDirs.append(ARMLibDirs, ARMLibDirs + llvm::array_lengthof(ARMLibDirs)); + Triples.append(ARMTriples, ARMTriples + llvm::array_lengthof(ARMTriples)); + } else if (HostArch == llvm::Triple::x86_64) { + static const char *const X86_64LibDirs[] = { "/lib64", "/lib" }; + static const char *const X86_64Triples[] = { + "x86_64-linux-gnu", + "x86_64-unknown-linux-gnu", + "x86_64-pc-linux-gnu", + "x86_64-redhat-linux6E", + "x86_64-redhat-linux", + "x86_64-suse-linux", + "x86_64-manbo-linux-gnu", + "x86_64-linux-gnu", + "x86_64-slackware-linux" }; - const std::string InstallSuffixes[] = { - "/../../..", - "/../../../..", - "/../../../.." + LibDirs.append(X86_64LibDirs, + X86_64LibDirs + llvm::array_lengthof(X86_64LibDirs)); + Triples.append(X86_64Triples, + X86_64Triples + llvm::array_lengthof(X86_64Triples)); + } else if (HostArch == llvm::Triple::x86) { + static const char *const X86LibDirs[] = { "/lib32", "/lib" }; + static const char *const X86Triples[] = { + "i686-linux-gnu", + "i686-pc-linux-gnu", + "i486-linux-gnu", + "i386-linux-gnu", + "i686-redhat-linux", + "i586-redhat-linux", + "i386-redhat-linux", + "i586-suse-linux", + "i486-slackware-linux" }; - // Only look at the final, weird Ubuntu suffix for i386-linux-gnu. - const unsigned NumSuffixes = (llvm::array_lengthof(Suffixes) - - (CandidateTriple != "i386-linux-gnu")); - for (unsigned i = 0; i < NumSuffixes; ++i) { - StringRef Suffix = Suffixes[i]; - llvm::error_code EC; - for (llvm::sys::fs::directory_iterator LI(LibDir + Suffix, EC), LE; - !EC && LI != LE; LI = LI.increment(EC)) { - StringRef VersionText = llvm::sys::path::filename(LI->path()); - GCCVersion CandidateVersion = GCCVersion::Parse(VersionText); - static const GCCVersion MinVersion = { 4, 1, 1 }; - if (CandidateVersion < MinVersion) - continue; - if (CandidateVersion <= BestVersion) - continue; - if (!PathExists(LI->path() + "/crtbegin.o")) - continue; + LibDirs.append(X86LibDirs, X86LibDirs + llvm::array_lengthof(X86LibDirs)); + Triples.append(X86Triples, X86Triples + llvm::array_lengthof(X86Triples)); + } else if (HostArch == llvm::Triple::ppc) { + static const char *const PPCLibDirs[] = { "/lib32", "/lib" }; + static const char *const PPCTriples[] = { + "powerpc-linux-gnu", + "powerpc-unknown-linux-gnu" + }; + LibDirs.append(PPCLibDirs, PPCLibDirs + llvm::array_lengthof(PPCLibDirs)); + Triples.append(PPCTriples, PPCTriples + llvm::array_lengthof(PPCTriples)); + } else if (HostArch == llvm::Triple::ppc64) { + static const char *const PPC64LibDirs[] = { "/lib64", "/lib" }; + static const char *const PPC64Triples[] = { + "powerpc64-unknown-linux-gnu" + }; + LibDirs.append(PPC64LibDirs, + PPC64LibDirs + llvm::array_lengthof(PPC64LibDirs)); + Triples.append(PPC64Triples, + PPC64Triples + llvm::array_lengthof(PPC64Triples)); + } +} - BestVersion = CandidateVersion; - GccTriple = CandidateTriple.str(); - // FIXME: We hack together the directory name here instead of - // using LI to ensure stable path separators across Windows and - // Linux. - GccInstallPath = LibDir + Suffixes[i] + "/" + VersionText.str(); - GccParentLibPath = GccInstallPath + InstallSuffixes[i]; - IsValid = true; - } +void Linux::GCCInstallationDetector::ScanLibDirForGCCTriple( + llvm::Triple::ArchType HostArch, const std::string &LibDir, + StringRef CandidateTriple) { + // There are various different suffixes involving the triple we + // check for. We also record what is necessary to walk from each back + // up to the lib directory. + const std::string Suffixes[] = { + "/gcc/" + CandidateTriple.str(), + "/" + CandidateTriple.str() + "/gcc/" + CandidateTriple.str(), + + // Ubuntu has a strange mis-matched pair of triples that this happens to + // match. + // FIXME: It may be worthwhile to generalize this and look for a second + // triple. + "/i386-linux-gnu/gcc/" + CandidateTriple.str() + }; + const std::string InstallSuffixes[] = { + "/../../..", + "/../../../..", + "/../../../.." + }; + // Only look at the final, weird Ubuntu suffix for i386-linux-gnu. + const unsigned NumSuffixes = (llvm::array_lengthof(Suffixes) - + (HostArch != llvm::Triple::x86)); + for (unsigned i = 0; i < NumSuffixes; ++i) { + StringRef Suffix = Suffixes[i]; + llvm::error_code EC; + for (llvm::sys::fs::directory_iterator LI(LibDir + Suffix, EC), LE; + !EC && LI != LE; LI = LI.increment(EC)) { + StringRef VersionText = llvm::sys::path::filename(LI->path()); + GCCVersion CandidateVersion = GCCVersion::Parse(VersionText); + static const GCCVersion MinVersion = { "4.1.1", 4, 1, 1, "" }; + if (CandidateVersion < MinVersion) + continue; + if (CandidateVersion <= Version) + continue; + if (!llvm::sys::fs::exists(LI->path() + "/crtbegin.o")) + continue; + + Version = CandidateVersion; + GccTriple = CandidateTriple.str(); + // FIXME: We hack together the directory name here instead of + // using LI to ensure stable path separators across Windows and + // Linux. + GccInstallPath = LibDir + Suffixes[i] + "/" + VersionText.str(); + GccParentLibPath = GccInstallPath + InstallSuffixes[i]; + IsValid = true; } } -}; } -static void addPathIfExists(const std::string &Path, - ToolChain::path_list &Paths) { - if (PathExists(Path)) Paths.push_back(Path); +static void addPathIfExists(Twine Path, ToolChain::path_list &Paths) { + if (llvm::sys::fs::exists(Path)) Paths.push_back(Path.str()); +} + +/// \brief Get our best guess at the multiarch triple for a target. +/// +/// Debian-based systems are starting to use a multiarch setup where they use +/// a target-triple directory in the library and header search paths. +/// Unfortunately, this triple does not align with the vanilla target triple, +/// so we provide a rough mapping here. +static std::string getMultiarchTriple(const llvm::Triple TargetTriple, + StringRef SysRoot) { + // For most architectures, just use whatever we have rather than trying to be + // clever. + switch (TargetTriple.getArch()) { + default: + return TargetTriple.str(); + *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201112091830.pB9IUhbm044635>