From d2e6cf1d1c6468396ec057119c32aa58b1ee5ac9 Mon Sep 17 00:00:00 2001 From: rdivacky Date: Sat, 6 Mar 2010 09:23:02 +0000 Subject: Update clang to r97873. --- lib/AST/ASTContext.cpp | 8 ++- lib/AST/DeclBase.cpp | 10 +++ lib/Basic/Targets.cpp | 35 +++++++--- lib/Basic/Version.cpp | 6 +- lib/Checker/Environment.cpp | 8 +-- lib/Checker/GRExprEngine.cpp | 7 +- lib/Checker/GRState.cpp | 14 ++-- lib/Checker/SymbolManager.cpp | 10 ++- lib/CodeGen/CGBlocks.cpp | 17 ++++- lib/CodeGen/CGBlocks.h | 4 +- lib/CodeGen/CGBuiltin.cpp | 48 ++++++++++++++ lib/CodeGen/CGCXX.cpp | 6 ++ lib/CodeGen/CGExpr.cpp | 10 +++ lib/CodeGen/CGExprConstant.cpp | 4 +- lib/CodeGen/CGExprScalar.cpp | 2 + lib/CodeGen/CGStmt.cpp | 11 ++-- lib/CodeGen/CodeGenFunction.h | 1 + lib/CodeGen/CodeGenModule.cpp | 60 +++++++++++++++-- lib/CodeGen/CodeGenModule.h | 10 +++ lib/CodeGen/Mangle.cpp | 66 +++++++++++++++---- lib/CodeGen/Mangle.h | 17 ++++- lib/CodeGen/TargetInfo.cpp | 81 +++++++++++++++++++++++ lib/CodeGen/TargetInfo.h | 17 +++++ lib/Driver/Driver.cpp | 4 ++ lib/Driver/HostInfo.cpp | 46 +++++++++++++ lib/Driver/ToolChains.cpp | 60 +++++++++++++++++ lib/Driver/ToolChains.h | 20 ++++++ lib/Frontend/ASTUnit.cpp | 3 +- lib/Frontend/CacheTokens.cpp | 4 +- lib/Frontend/InitHeaderSearch.cpp | 11 ++++ lib/Frontend/RewriteObjC.cpp | 26 ++++++++ lib/Headers/smmintrin.h | 130 ++++++++++++++++++++++++++++++++++++ lib/Lex/PPMacroExpansion.cpp | 1 + lib/Sema/Sema.h | 8 ++- lib/Sema/SemaDeclCXX.cpp | 31 +++++++-- lib/Sema/SemaExpr.cpp | 134 ++++++++++++++++++++++++++++++-------- lib/Sema/SemaExprCXX.cpp | 2 +- lib/Sema/SemaInit.cpp | 3 +- lib/Sema/SemaOverload.cpp | 41 +++++++----- lib/Sema/SemaType.cpp | 3 +- lib/Sema/TreeTransform.h | 2 +- 41 files changed, 861 insertions(+), 120 deletions(-) create mode 100644 lib/Headers/smmintrin.h (limited to 'lib') diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index e091bf1..d8c1c84 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -2240,14 +2240,16 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols, /// the given interface decl and the conforming protocol list. QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT, ObjCProtocolDecl **Protocols, - unsigned NumProtocols) { + unsigned NumProtocols, + unsigned Quals) { llvm::FoldingSetNodeID ID; ObjCObjectPointerType::Profile(ID, InterfaceT, Protocols, NumProtocols); + Qualifiers Qs = Qualifiers::fromCVRMask(Quals); void *InsertPos = 0; if (ObjCObjectPointerType *QT = ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos)) - return QualType(QT, 0); + return getQualifiedType(QualType(QT, 0), Qs); // Sort the protocol list alphabetically to canonicalize it. QualType Canonical; @@ -2282,7 +2284,7 @@ QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT, Types.push_back(QType); ObjCObjectPointerTypes.InsertNode(QType, InsertPos); - return QualType(QType, 0); + return getQualifiedType(QualType(QType, 0), Qs); } /// getObjCInterfaceType - Return the unique reference to the type for the diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 47b7e7e..9db6ae1 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -46,6 +46,16 @@ const char *Decl::getDeclKindName() const { } } +void Decl::setInvalidDecl(bool Invalid) { + InvalidDecl = Invalid; + if (Invalid) { + // Defensive maneuver for ill-formed code: we're likely not to make it to + // a point where we set the access specifier, so default it to "public" + // to avoid triggering asserts elsewhere in the front end. + setAccess(AS_public); + } +} + const char *DeclContext::getDeclKindName() const { switch (DeclKind) { default: assert(0 && "Declaration context not in DeclNodes.def!"); diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index b8fe535..ae6d5df 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -734,8 +734,10 @@ void X86TargetInfo::getDefaultFeatures(const std::string &CPU, bool X86TargetInfo::setFeatureEnabled(llvm::StringMap &Features, const std::string &Name, bool Enabled) const { - // FIXME: This *really* should not be here. - if (!Features.count(Name) && Name != "sse4") + // FIXME: This *really* should not be here. We need some way of translating + // options into llvm subtarget features. + if (!Features.count(Name) && + (Name != "sse4" && Name != "sse4.2" && Name != "sse4.1")) return false; if (Enabled) { @@ -751,9 +753,12 @@ bool X86TargetInfo::setFeatureEnabled(llvm::StringMap &Features, else if (Name == "ssse3") Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = Features["ssse3"] = true; - else if (Name == "sse4") + else if (Name == "sse4" || Name == "sse4.2") Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = Features["ssse3"] = Features["sse41"] = Features["sse42"] = true; + else if (Name == "sse4.1") + Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = + Features["ssse3"] = Features["sse41"] = true; else if (Name == "3dnow") Features["3dnowa"] = true; else if (Name == "3dnowa") @@ -775,6 +780,10 @@ bool X86TargetInfo::setFeatureEnabled(llvm::StringMap &Features, Features["ssse3"] = Features["sse41"] = Features["sse42"] = false; else if (Name == "sse4") Features["sse41"] = Features["sse42"] = false; + else if (Name == "sse4.2") + Features["sse42"] = false; + else if (Name == "sse4.1") + Features["sse41"] = Features["sse42"] = false; else if (Name == "3dnow") Features["3dnow"] = Features["3dnowa"] = false; else if (Name == "3dnowa") @@ -1207,6 +1216,8 @@ class ARMTargetInfo : public TargetInfo { unsigned SoftFloat : 1; unsigned SoftFloatABI : 1; + static const Builtin::Info BuiltinInfo[]; + public: ARMTargetInfo(const std::string &TripleStr) : TargetInfo(TripleStr), ABI("aapcs-linux"), CPU("arm1136j-s") @@ -1393,9 +1404,8 @@ public: } virtual void getTargetBuiltins(const Builtin::Info *&Records, unsigned &NumRecords) const { - // FIXME: Implement. - Records = 0; - NumRecords = 0; + Records = BuiltinInfo; + NumRecords = clang::ARM::LastTSBuiltin-Builtin::FirstTSBuiltin; } virtual const char *getVAListDeclaration() const { return "typedef char* __builtin_va_list;"; @@ -1460,6 +1470,12 @@ void ARMTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases, Aliases = GCCRegAliases; NumAliases = llvm::array_lengthof(GCCRegAliases); } + +const Builtin::Info ARMTargetInfo::BuiltinInfo[] = { +#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, false }, +#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER, false }, +#include "clang/Basic/BuiltinsARM.def" +}; } // end anonymous namespace. @@ -1892,9 +1908,10 @@ namespace { FloatFormat = &llvm::APFloat::IEEEsingle; DoubleFormat = &llvm::APFloat::IEEEsingle; LongDoubleFormat = &llvm::APFloat::IEEEsingle; - DescriptionString = "E-p:32:32:32-a0:32:32" - "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64" - "-f32:32:32-f64:32:64-n32"; + DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:32-" + "i16:16:32-i32:32:32-i64:32:32-" + "f32:32:32-f64:64:64-v64:64:64-" + "v128:128:128-a0:0:64-n32"; } virtual void getTargetDefines(const LangOptions &Opts, diff --git a/lib/Basic/Version.cpp b/lib/Basic/Version.cpp index 4d90305..dc87d14 100644 --- a/lib/Basic/Version.cpp +++ b/lib/Basic/Version.cpp @@ -45,7 +45,7 @@ std::string getClangRevision() { std::string revision; llvm::raw_string_ostream OS(revision); OS << strtol(SVN_REVISION, 0, 10); - return revision; + return OS.str(); } #endif return ""; @@ -58,7 +58,7 @@ std::string getClangFullRepositoryVersion() { const std::string &Revision = getClangRevision(); if (!Revision.empty()) OS << ' ' << Revision; - return buf; + return OS.str(); } std::string getClangFullVersion() { @@ -69,7 +69,7 @@ std::string getClangFullVersion() { #endif OS << "clang version " CLANG_VERSION_STRING " (" << getClangFullRepositoryVersion() << ')'; - return buf; + return OS.str(); } } // end namespace clang diff --git a/lib/Checker/Environment.cpp b/lib/Checker/Environment.cpp index c2c9190..671cf89 100644 --- a/lib/Checker/Environment.cpp +++ b/lib/Checker/Environment.cpp @@ -78,12 +78,12 @@ Environment EnvironmentManager::BindExpr(Environment Env, const Stmt *S, if (V.isUnknown()) { if (Invalidate) - return Environment(F.Remove(Env.ExprBindings, S), Env.ACtx); + return Environment(F.Remove(Env.ExprBindings, S)); else return Env; } - return Environment(F.Add(Env.ExprBindings, S, V), Env.ACtx); + return Environment(F.Add(Env.ExprBindings, S, V)); } namespace { @@ -109,12 +109,12 @@ EnvironmentManager::RemoveDeadBindings(Environment Env, const Stmt *S, const GRState *ST, llvm::SmallVectorImpl &DRoots) { - CFG &C = *Env.getAnalysisContext().getCFG(); + CFG &C = *SymReaper.getLocationContext()->getCFG(); // We construct a new Environment object entirely, as this is cheaper than // individually removing all the subexpression bindings (which will greatly // outnumber block-level expression bindings). - Environment NewEnv = getInitialEnvironment(&Env.getAnalysisContext()); + Environment NewEnv = getInitialEnvironment(); // Iterate over the block-expr bindings. for (Environment::iterator I = Env.begin(), E = Env.end(); diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index ad229c7..2ea689e 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -477,8 +477,9 @@ void GRExprEngine::ProcessStmt(CFGElement CE, GRStmtNodeBuilder& builder) { // Create the cleaned state. const ExplodedNode *BasePred = Builder->getBasePredecessor(); - SymbolReaper SymReaper(BasePred->getLiveVariables(), SymMgr, - BasePred->getLocationContext()->getCurrentStackFrame()); + + SymbolReaper SymReaper(BasePred->getLocationContext(), SymMgr); + CleanedState = AMgr.shouldPurgeDead() ? StateMgr.RemoveDeadBindings(EntryNode->getState(), CurrentStmt, SymReaper) : EntryNode->getState(); @@ -3319,7 +3320,7 @@ struct DOTGraphTraits : Out << "\\|StateID: " << (void*) N->getState() << "\\|"; const GRState *state = N->getState(); - state->printDOT(Out); + state->printDOT(Out, *N->getLocationContext()->getCFG()); Out << "\\l"; return Out.str(); diff --git a/lib/Checker/GRState.cpp b/lib/Checker/GRState.cpp index 592f930..97ede1d 100644 --- a/lib/Checker/GRState.cpp +++ b/lib/Checker/GRState.cpp @@ -99,7 +99,7 @@ const GRState *GRState::BindExpr(const Stmt* Ex, SVal V, bool Invalidate) const{ const GRState* GRStateManager::getInitialState(const LocationContext *InitLoc) { GRState State(this, - EnvMgr.getInitialEnvironment(InitLoc->getAnalysisContext()), + EnvMgr.getInitialEnvironment(), StoreMgr->getInitialStore(InitLoc), GDMFactory.GetEmptyMap()); @@ -131,14 +131,12 @@ const GRState* GRState::makeWithStore(Store store) const { // State pretty-printing. //===----------------------------------------------------------------------===// -void GRState::print(llvm::raw_ostream& Out, const char* nl, +void GRState::print(llvm::raw_ostream& Out, CFG &C, const char* nl, const char* sep) const { // Print the store. GRStateManager &Mgr = getStateManager(); Mgr.getStoreManager().print(getStore(), Out, nl, sep); - CFG &C = *getAnalysisContext().getCFG(); - // Print Subexpression bindings. bool isFirst = true; @@ -186,12 +184,12 @@ void GRState::print(llvm::raw_ostream& Out, const char* nl, } } -void GRState::printDOT(llvm::raw_ostream& Out) const { - print(Out, "\\l", "\\|"); +void GRState::printDOT(llvm::raw_ostream& Out, CFG &C) const { + print(Out, C, "\\l", "\\|"); } -void GRState::printStdErr() const { - print(llvm::errs()); +void GRState::printStdErr(CFG &C) const { + print(llvm::errs(), C); } //===----------------------------------------------------------------------===// diff --git a/lib/Checker/SymbolManager.cpp b/lib/Checker/SymbolManager.cpp index f2d630c..65a46e3 100644 --- a/lib/Checker/SymbolManager.cpp +++ b/lib/Checker/SymbolManager.cpp @@ -215,13 +215,17 @@ bool SymbolReaper::isLive(SymbolRef sym) { return isa(sym); } +bool SymbolReaper::isLive(const Stmt* Loc, const Stmt* ExprVal) const { + return LCtx->getLiveVariables()->isLive(Loc, ExprVal); +} + bool SymbolReaper::isLive(const Stmt *Loc, const VarRegion *VR) const { const StackFrameContext *SFC = VR->getStackFrame(); - if (SFC == CurrentStackFrame) - return Liveness.isLive(Loc, VR->getDecl()); + if (SFC == LCtx->getCurrentStackFrame()) + return LCtx->getLiveVariables()->isLive(Loc, VR->getDecl()); else - return SFC->isParentOf(CurrentStackFrame); + return SFC->isParentOf(LCtx->getCurrentStackFrame()); } SymbolVisitor::~SymbolVisitor() {} diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 7076067..c10a401 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -154,7 +154,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { { // C = BuildBlockStructInitlist(); - unsigned int flags = BLOCK_HAS_OBJC_TYPE; + unsigned int flags = BLOCK_HAS_SIGNATURE; // We run this first so that we set BlockHasCopyDispose from the entire // block literal. @@ -184,6 +184,18 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { Elts[0] = C; // __flags + { + QualType BPT = BE->getType(); + const FunctionType *ftype = BPT->getPointeeType()->getAs(); + QualType ResultType = ftype->getResultType(); + + CallArgList Args; + CodeGenTypes &Types = CGM.getTypes(); + const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, Args, + CC_Default, false); + if (CGM.ReturnTypeUsesSret(FnInfo)) + flags |= BLOCK_USE_STRET; + } const llvm::IntegerType *IntTy = cast( CGM.getTypes().ConvertType(CGM.getContext().IntTy)); C = llvm::ConstantInt::get(IntTy, flags); @@ -200,6 +212,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { // Optimize to being a global block. Elts[0] = CGM.getNSConcreteGlobalBlock(); + Elts[1] = llvm::ConstantInt::get(IntTy, flags|BLOCK_IS_GLOBAL); C = llvm::ConstantStruct::get(VMContext, Elts, false); @@ -604,7 +617,7 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) { // Flags LiteralFields[1] = - llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_OBJC_TYPE); + llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE); // Reserved LiteralFields[2] = llvm::Constant::getNullValue(IntTy); diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h index 39f26f8..e91319f 100644 --- a/lib/CodeGen/CGBlocks.h +++ b/lib/CodeGen/CGBlocks.h @@ -54,10 +54,12 @@ public: BLOCK_HAS_COPY_DISPOSE = (1 << 25), BLOCK_HAS_CXX_OBJ = (1 << 26), BLOCK_IS_GLOBAL = (1 << 28), - BLOCK_HAS_OBJC_TYPE = (1 << 30) + BLOCK_USE_STRET = (1 << 29), + BLOCK_HAS_SIGNATURE = (1 << 30) }; }; + class BlockModule : public BlockBase { ASTContext &Context; llvm::Module &TheModule; diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 0f5e90f..706e441 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -387,6 +387,22 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Value *Result = getTargetHooks().encodeReturnAddress(*this, Address); return RValue::get(Result); } + case Builtin::BI__builtin_dwarf_sp_column: { + const llvm::IntegerType *Ty + = cast(ConvertType(E->getType())); + int Column = getTargetHooks().getDwarfEHStackPointer(CGM); + if (Column == -1) { + CGM.ErrorUnsupported(E, "__builtin_dwarf_sp_column"); + return RValue::get(llvm::UndefValue::get(Ty)); + } + return RValue::get(llvm::ConstantInt::get(Ty, Column, true)); + } + case Builtin::BI__builtin_init_dwarf_reg_size_table: { + Value *Address = EmitScalarExpr(E->getArg(0)); + if (getTargetHooks().initDwarfEHRegSizeTable(*this, Address)) + CGM.ErrorUnsupported(E, "__builtin_init_dwarf_reg_size_table"); + return RValue::get(llvm::UndefValue::get(ConvertType(E->getType()))); + } case Builtin::BI__builtin_eh_return: { Value *Int = EmitScalarExpr(E->getArg(0)); Value *Ptr = EmitScalarExpr(E->getArg(1)); @@ -666,6 +682,23 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Value *F = CGM.getIntrinsic(Intrinsic::pow, &ArgType, 1); return RValue::get(Builder.CreateCall2(F, Base, Exponent, "tmp")); } + + case Builtin::BI__builtin_signbit: + case Builtin::BI__builtin_signbitf: + case Builtin::BI__builtin_signbitl: { + LLVMContext &C = CGM.getLLVMContext(); + + Value *Arg = EmitScalarExpr(E->getArg(0)); + const llvm::Type *ArgTy = Arg->getType(); + if (ArgTy->isPPC_FP128Ty()) + break; // FIXME: I'm not sure what the right implementation is here. + int ArgWidth = ArgTy->getPrimitiveSizeInBits(); + const llvm::Type *ArgIntTy = llvm::IntegerType::get(C, ArgWidth); + Value *BCArg = Builder.CreateBitCast(Arg, ArgIntTy); + Value *ZeroCmp = llvm::Constant::getNullValue(ArgIntTy); + Value *Result = Builder.CreateICmpSLT(BCArg, ZeroCmp); + return RValue::get(Builder.CreateZExt(Result, ConvertType(E->getType()))); + } } // If this is an alias for a libm function (e.g. __builtin_sin) turn it into @@ -735,6 +768,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { switch (Target.getTriple().getArch()) { + case llvm::Triple::arm: + case llvm::Triple::thumb: + return EmitARMBuiltinExpr(BuiltinID, E); case llvm::Triple::x86: case llvm::Triple::x86_64: return EmitX86BuiltinExpr(BuiltinID, E); @@ -746,6 +782,18 @@ Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID, } } +Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, + const CallExpr *E) { + switch (BuiltinID) { + default: return 0; + + case ARM::BI__builtin_thread_pointer: { + Value *AtomF = CGM.getIntrinsic(Intrinsic::arm_thread_pointer, 0, 0); + return Builder.CreateCall(AtomF); + } + } +} + Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E) { diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 4889fc0..7752cf7 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -142,6 +142,12 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl, return true; } + llvm::GlobalValue::LinkageTypes TargetLinkage + = getFunctionLinkage(cast(TargetDecl.getDecl())); + + if (llvm::GlobalValue::isWeakForLinker(TargetLinkage)) + return true; + // Derive the type for the alias. const llvm::PointerType *AliasType = getTypes().GetFunctionType(AliasDecl)->getPointerTo(); diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 030d2c9..dc9ecd6 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1062,6 +1062,16 @@ static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF, LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { const NamedDecl *ND = E->getDecl(); + if (ND->hasAttr()) { + const ValueDecl* VD = cast(ND); + llvm::Constant *Aliasee = CGM.GetWeakRefReference(VD); + + Qualifiers Quals = MakeQualifiers(E->getType()); + LValue LV = LValue::MakeAddr(Aliasee, Quals); + + return LV; + } + if (const VarDecl *VD = dyn_cast(ND)) { // Check if this is a global variable. diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 3df552d..f0d82a8 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -761,7 +761,9 @@ public: return C; } case Expr::DeclRefExprClass: { - NamedDecl *Decl = cast(E)->getDecl(); + ValueDecl *Decl = cast(E)->getDecl(); + if (Decl->hasAttr()) + return CGM.GetWeakRefReference(Decl); if (const FunctionDecl *FD = dyn_cast(Decl)) return CGM.GetAddrOfFunction(FD); if (const VarDecl* VD = dyn_cast(Decl)) { diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index db0998b..7e26971 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1888,6 +1888,8 @@ LValue CodeGenFunction::EmitObjCIsaExpr(const ObjCIsaExpr *E) { V = CreateTempAlloca(ClassPtrTy, "resval"); llvm::Value *Src = EmitScalarExpr(BaseExpr); Builder.CreateStore(Src, V); + LValue LV = LValue::MakeAddr(V, MakeQualifiers(E->getType())); + V = ScalarExprEmitter(*this).EmitLoadOfLValue(LV, E->getType()); } else { if (E->isArrow()) diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 008a480..a889e55 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -915,18 +915,17 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) { TargetInfo::ConstraintInfo Info(S.getOutputConstraint(i), S.getOutputName(i)); - assert(Target.validateOutputConstraint(Info) && - "Failed to parse output constraint"); + bool IsValid = Target.validateOutputConstraint(Info); (void)IsValid; + assert(IsValid && "Failed to parse output constraint"); OutputConstraintInfos.push_back(Info); } for (unsigned i = 0, e = S.getNumInputs(); i != e; i++) { TargetInfo::ConstraintInfo Info(S.getInputConstraint(i), S.getInputName(i)); - assert(Target.validateInputConstraint(OutputConstraintInfos.data(), - S.getNumOutputs(), - Info) && - "Failed to parse input constraint"); + bool IsValid = Target.validateInputConstraint(OutputConstraintInfos.data(), + S.getNumOutputs(), Info); + assert(IsValid && "Failed to parse input constraint"); (void)IsValid; InputConstraintInfos.push_back(Info); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index d582c0d..88d6413 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1122,6 +1122,7 @@ public: /// is unhandled by the current target. llvm::Value *EmitTargetBuiltinExpr(unsigned BuiltinID, const CallExpr *E); + llvm::Value *EmitARMBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitPPCBuiltinExpr(unsigned BuiltinID, const CallExpr *E); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 91c7322..d6a56da 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -33,6 +33,7 @@ #include "llvm/Module.h" #include "llvm/Intrinsics.h" #include "llvm/LLVMContext.h" +#include "llvm/ADT/Triple.h" #include "llvm/Target/TargetData.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; @@ -89,6 +90,10 @@ void CodeGenModule::Release() { EmitLLVMUsed(); } +bool CodeGenModule::isTargetDarwin() const { + return getContext().Target.getTriple().getOS() == llvm::Triple::Darwin; +} + /// ErrorUnsupported - Print out an error that codegen doesn't support the /// specified stmt yet. void CodeGenModule::ErrorUnsupported(const Stmt *S, const char *Type, @@ -619,9 +624,41 @@ bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) { return false; } +llvm::Constant *CodeGenModule::GetWeakRefReference(const ValueDecl *VD) { + const AliasAttr *AA = VD->getAttr(); + assert(AA && "No alias?"); + + const llvm::Type *DeclTy = getTypes().ConvertTypeForMem(VD->getType()); + + // Unique the name through the identifier table. + const char *AliaseeName = + getContext().Idents.get(AA->getAliasee()).getNameStart(); + + // See if there is already something with the target's name in the module. + llvm::GlobalValue *Entry = GlobalDeclMap[AliaseeName]; + + llvm::Constant *Aliasee; + if (isa(DeclTy)) + Aliasee = GetOrCreateLLVMFunction(AliaseeName, DeclTy, GlobalDecl()); + else + Aliasee = GetOrCreateLLVMGlobal(AliaseeName, + llvm::PointerType::getUnqual(DeclTy), 0); + if (!Entry) { + llvm::GlobalValue* F = cast(Aliasee); + F->setLinkage(llvm::Function::ExternalWeakLinkage); + WeakRefReferences.insert(F); + } + + return Aliasee; +} + void CodeGenModule::EmitGlobal(GlobalDecl GD) { const ValueDecl *Global = cast(GD.getDecl()); + // Weak references don't produce any output by themselves. + if (Global->hasAttr()) + return; + // If this is an alias definition (which otherwise looks like a declaration) // emit it now. if (Global->hasAttr()) @@ -708,6 +745,14 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName, // Lookup the entry, lazily creating it if necessary. llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName]; if (Entry) { + if (WeakRefReferences.count(Entry)) { + const FunctionDecl *FD = cast_or_null(D.getDecl()); + if (FD && !FD->hasAttr()) + Entry->setLinkage(llvm::Function::ExternalLinkage); + + WeakRefReferences.erase(Entry); + } + if (Entry->getType()->getElementType() == Ty) return Entry; @@ -753,17 +798,17 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName, // synthesized. else if (const CXXConstructorDecl *CD = dyn_cast(FD)) { if (CD->isImplicit()) { - assert (CD->isUsed()); + assert(CD->isUsed() && "Sema doesn't consider constructor as used."); DeferredDeclsToEmit.push_back(D); } } else if (const CXXDestructorDecl *DD = dyn_cast(FD)) { if (DD->isImplicit()) { - assert (DD->isUsed()); + assert(DD->isUsed() && "Sema doesn't consider destructor as used."); DeferredDeclsToEmit.push_back(D); } } else if (const CXXMethodDecl *MD = dyn_cast(FD)) { if (MD->isCopyAssignment() && MD->isImplicit()) { - assert (MD->isUsed()); + assert(MD->isUsed() && "Sema doesn't consider CopyAssignment as used."); DeferredDeclsToEmit.push_back(D); } } @@ -817,6 +862,13 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMGlobal(const char *MangledName, // Lookup the entry, lazily creating it if necessary. llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName]; if (Entry) { + if (WeakRefReferences.count(Entry)) { + if (D && !D->hasAttr()) + Entry->setLinkage(llvm::Function::ExternalLinkage); + + WeakRefReferences.erase(Entry); + } + if (Entry->getType() == Ty) return Entry; @@ -1203,7 +1255,7 @@ static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) { const FunctionDecl *D = cast(GD.getDecl()); const llvm::FunctionType *Ty = getTypes().GetFunctionType(GD); - + getMangleContext().mangleInitDiscriminator(); // Get or create the prototype for the function. llvm::Constant *Entry = GetAddrOfFunction(GD, Ty); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index ac83326..c86f8b4 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -29,6 +29,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/ValueHandle.h" #include @@ -117,6 +118,11 @@ class CodeGenModule : public BlockModule { /// pointer lookups instead of full string lookups. llvm::DenseMap GlobalDeclMap; + // WeakRefReferences - A set of references that have only been seen via + // a weakref so far. This is used to remove the weak of the reference if we ever + // see a direct reference or a definition. + llvm::SmallPtrSet WeakRefReferences; + /// \brief Contains the strings used for mangled names. /// /// FIXME: Eventually, this should map from the semantic/canonical @@ -198,6 +204,7 @@ public: const llvm::TargetData &getTargetData() const { return TheTargetData; } llvm::LLVMContext &getLLVMContext() { return VMContext; } const TargetCodeGenInfo &getTargetCodeGenInfo() const; + bool isTargetDarwin() const; /// getDeclVisibilityMode - Compute the visibility of the decl \arg D. LangOptions::VisibilityMode getDeclVisibilityMode(const Decl *D) const; @@ -243,6 +250,9 @@ public: void BuildThunksForVirtual(GlobalDecl GD); void BuildThunksForVirtualRecursive(GlobalDecl GD, GlobalDecl BaseOGD); + /// GetWeakRefReference - Get a reference to the target of VD. + llvm::Constant *GetWeakRefReference(const ValueDecl *VD); + /// BuildThunk - Build a thunk for the given method. llvm::Constant *BuildThunk(GlobalDecl GD, bool Extern, const ThunkAdjustment &ThisAdjustment); diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 64743c7..20d54b3 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -37,7 +37,19 @@ using namespace clang; using namespace CodeGen; namespace { - + +static const DeclContext *GetLocalClassFunctionDeclContext( + const DeclContext *DC) { + if (isa(DC)) { + while (!DC->isNamespace() && !DC->isTranslationUnit() && + !isa(DC)) + DC = DC->getParent(); + if (isa(DC)) + return DC; + } + return 0; +} + static const CXXMethodDecl *getStructor(const CXXMethodDecl *MD) { assert((isa(MD) || isa(MD)) && "Passed in decl is not a ctor or dtor!"); @@ -61,7 +73,7 @@ class CXXNameMangler { const CXXMethodDecl *Structor; unsigned StructorType; - + llvm::DenseMap Substitutions; ASTContext &getASTContext() const { return Context.getASTContext(); } @@ -128,11 +140,12 @@ private: void mangleUnscopedTemplateName(const TemplateDecl *ND); void mangleSourceName(const IdentifierInfo *II); void mangleLocalName(const NamedDecl *ND); - void mangleNestedName(const NamedDecl *ND, const DeclContext *DC); + void mangleNestedName(const NamedDecl *ND, const DeclContext *DC, + bool NoFunction=false); void mangleNestedName(const TemplateDecl *TD, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs); - void manglePrefix(const DeclContext *DC); + void manglePrefix(const DeclContext *DC, bool NoFunction=false); void mangleTemplatePrefix(const TemplateDecl *ND); void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity); void mangleQualifiers(Qualifiers Quals); @@ -342,7 +355,12 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { // ::= // const DeclContext *DC = ND->getDeclContext(); - + + if (GetLocalClassFunctionDeclContext(DC)) { + mangleLocalName(ND); + return; + } + // If this is an extern variable declared locally, the relevant DeclContext // is that of the containing namespace, or the translation unit. if (isa(DC) && ND->hasLinkage()) @@ -603,7 +621,8 @@ void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) { } void CXXNameMangler::mangleNestedName(const NamedDecl *ND, - const DeclContext *DC) { + const DeclContext *DC, + bool NoFunction) { // ::= N [] E // ::= N [] E @@ -616,8 +635,9 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND, if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { mangleTemplatePrefix(TD); mangleTemplateArgs(*TemplateArgs); - } else { - manglePrefix(DC); + } + else { + manglePrefix(DC, NoFunction); mangleUnqualifiedName(ND); } @@ -640,18 +660,35 @@ void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { // := Z E [] // := Z E s [] // := _ + const DeclContext *DC = ND->getDeclContext(); Out << 'Z'; - if (const ObjCMethodDecl *MD = dyn_cast(ND->getDeclContext())) + if (const ObjCMethodDecl *MD = dyn_cast(DC)) mangleObjCMethodName(MD); + else if (const DeclContext *CDC = GetLocalClassFunctionDeclContext(DC)) { + mangleFunctionEncoding(cast(CDC)); + Out << 'E'; + mangleNestedName(ND, DC, true /*NoFunction*/); + + // FIXME. This still does not cover all cases. + unsigned disc; + if (Context.getNextDiscriminator(ND, disc)) { + if (disc < 10) + Out << '_' << disc; + else + Out << "__" << disc << '_'; + } + + return; + } else - mangleFunctionEncoding(cast(ND->getDeclContext())); + mangleFunctionEncoding(cast(DC)); Out << 'E'; mangleUnqualifiedName(ND); } -void CXXNameMangler::manglePrefix(const DeclContext *DC) { +void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { // ::= // ::= // ::= @@ -672,8 +709,11 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC) { if (const TemplateDecl *TD = isTemplate(cast(DC), TemplateArgs)) { mangleTemplatePrefix(TD); mangleTemplateArgs(*TemplateArgs); - } else { - manglePrefix(DC->getParent()); + } + else if(NoFunction && isa(DC)) + return; + else { + manglePrefix(DC->getParent(), NoFunction); mangleUnqualifiedName(cast(DC)); } diff --git a/lib/CodeGen/Mangle.h b/lib/CodeGen/Mangle.h index 8d96295..97f94b6 100644 --- a/lib/CodeGen/Mangle.h +++ b/lib/CodeGen/Mangle.h @@ -44,7 +44,9 @@ class MangleContext { ASTContext &Context; llvm::DenseMap AnonStructIds; - + unsigned Discriminator; + llvm::DenseMap Uniquifier; + public: explicit MangleContext(ASTContext &Context) : Context(Context) { } @@ -85,7 +87,20 @@ public: llvm::SmallVectorImpl &); void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, llvm::SmallVectorImpl &); + + void mangleInitDiscriminator() { + Discriminator = 0; + } + bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) { + unsigned &discriminator = Uniquifier[ND]; + if (!discriminator) + discriminator = ++Discriminator; + if (discriminator == 1) + return false; + disc = discriminator-2; + return true; + } /// @} }; diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index f4ec914..cb6a7df 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -328,6 +328,16 @@ public: void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const; + + int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const { + // Darwin uses different dwarf register numbers for EH. + if (CGM.isTargetDarwin()) return 5; + + return 4; + } + + bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, + llvm::Value *Address) const; }; } @@ -568,6 +578,51 @@ void X86_32TargetCodeGenInfo::SetTargetAttributes(const Decl *D, } } +bool X86_32TargetCodeGenInfo::initDwarfEHRegSizeTable( + CodeGen::CodeGenFunction &CGF, + llvm::Value *Address) const { + CodeGen::CGBuilderTy &Builder = CGF.Builder; + llvm::LLVMContext &Context = CGF.getLLVMContext(); + + const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); + llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4); + + // 0-7 are the eight integer registers; the order is different + // on Darwin (for EH), but the range is the same. + // 8 is %eip. + for (unsigned I = 0, E = 9; I != E; ++I) { + llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); + Builder.CreateStore(Four8, Slot); + } + + if (CGF.CGM.isTargetDarwin()) { + // 12-16 are st(0..4). Not sure why we stop at 4. + // These have size 16, which is sizeof(long double) on + // platforms with 8-byte alignment for that type. + llvm::Value *Sixteen8 = llvm::ConstantInt::get(i8, 16); + for (unsigned I = 12, E = 17; I != E; ++I) { + llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); + Builder.CreateStore(Sixteen8, Slot); + } + + } else { + // 9 is %eflags, which doesn't get a size on Darwin for some + // reason. + Builder.CreateStore(Four8, Builder.CreateConstInBoundsGEP1_32(Address, 9)); + + // 11-16 are st(0..5). Not sure why we stop at 5. + // These have size 12, which is sizeof(long double) on + // platforms with 4-byte alignment for that type. + llvm::Value *Twelve8 = llvm::ConstantInt::get(i8, 12); + for (unsigned I = 11, E = 17; I != E; ++I) { + llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); + Builder.CreateStore(Twelve8, Slot); + } + } + + return false; +} + namespace { /// X86_64ABIInfo - The X86_64 ABI information. class X86_64ABIInfo : public ABIInfo { @@ -656,6 +711,28 @@ public: class X86_64TargetCodeGenInfo : public TargetCodeGenInfo { public: X86_64TargetCodeGenInfo():TargetCodeGenInfo(new X86_64ABIInfo()) {} + + int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const { + return 7; + } + + bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, + llvm::Value *Address) const { + CodeGen::CGBuilderTy &Builder = CGF.Builder; + llvm::LLVMContext &Context = CGF.getLLVMContext(); + + const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); + llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8); + + // 0-16 are the 16 integer registers. + // 17 is %rip. + for (unsigned I = 0, E = 17; I != E; ++I) { + llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); + Builder.CreateStore(Eight8, Slot); + } + + return false; + } }; } @@ -1559,6 +1636,10 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo { public: ARMTargetCodeGenInfo(ARMABIInfo::ABIKind K) :TargetCodeGenInfo(new ARMABIInfo(K)) {} + + int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const { + return 13; + } }; } diff --git a/lib/CodeGen/TargetInfo.h b/lib/CodeGen/TargetInfo.h index 9e80081..f0a7824 100644 --- a/lib/CodeGen/TargetInfo.h +++ b/lib/CodeGen/TargetInfo.h @@ -56,6 +56,23 @@ namespace clang { /// through such registers. virtual bool extendPointerWithSExt() const { return false; } + /// Determines the DWARF register number for the stack pointer, for + /// exception-handling purposes. Implements __builtin_dwarf_sp_column. + /// + /// Returns -1 if the operation is unsupported by this target. + virtual int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const { + return -1; + } + + /// Initializes the given DWARF EH register-size table, a char*. + /// Implements __builtin_init_dwarf_reg_size_table. + /// + /// Returns true if the operation is unsupported by this target. + virtual bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, + llvm::Value *Address) const { + return true; + } + /// Performs the code-generation required to convert a return /// address as stored by the system into the actual address of the /// next instruction that will be executed. diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index ec8227e..64168b4 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1145,6 +1145,10 @@ const HostInfo *Driver::GetHostInfo(const char *TripleStr) const { llvm::PrettyStackTraceString CrashInfo("Constructing host"); llvm::Triple Triple(TripleStr); + // TCE is an osless target + if (Triple.getArchName() == "tce") + return createTCEHostInfo(*this, Triple); + switch (Triple.getOS()) { case llvm::Triple::AuroraUX: return createAuroraUXHostInfo(*this, Triple); diff --git a/lib/Driver/HostInfo.cpp b/lib/Driver/HostInfo.cpp index 18bb786..98b64f1 100644 --- a/lib/Driver/HostInfo.cpp +++ b/lib/Driver/HostInfo.cpp @@ -157,6 +157,46 @@ ToolChain *DarwinHostInfo::CreateToolChain(const ArgList &Args, return TC; } +// TCE Host Info + +/// TCEHostInfo - TCE host information implementation (see http://tce.cs.tut.fi) +class TCEHostInfo : public HostInfo { + +public: + TCEHostInfo(const Driver &D, const llvm::Triple &Triple); + ~TCEHostInfo() {}; + + virtual bool useDriverDriver() const; + + virtual types::ID lookupTypeForExtension(const char *Ext) const { + types::ID Ty = types::lookupTypeForExtension(Ext); + + if (Ty == types::TY_PP_Asm) + return types::TY_Asm; + + return Ty; + } + + virtual ToolChain *CreateToolChain(const ArgList &Args, + const char *ArchName) const; +}; + +TCEHostInfo::TCEHostInfo(const Driver &D, const llvm::Triple& Triple) + : HostInfo(D, Triple) { +} + +bool TCEHostInfo::useDriverDriver() const { + return false; +} + +ToolChain *TCEHostInfo::CreateToolChain(const ArgList &Args, + const char *ArchName) const { + llvm::Triple TCTriple(getTriple()); +// TCTriple.setArchName(ArchName); + return new toolchains::TCEToolChain(*this, TCTriple); +} + + // Unknown Host Info /// UnknownHostInfo - Generic host information to use for unknown hosts. @@ -536,6 +576,12 @@ clang::driver::createLinuxHostInfo(const Driver &D, } const HostInfo * +clang::driver::createTCEHostInfo(const Driver &D, + const llvm::Triple& Triple) { + return new TCEHostInfo(D, Triple); +} + +const HostInfo * clang::driver::createUnknownHostInfo(const Driver &D, const llvm::Triple& Triple) { return new UnknownHostInfo(D, Triple); diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index a7cd711..2f8d714 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -728,6 +728,66 @@ DerivedArgList *Generic_GCC::TranslateArgs(InputArgList &Args, return new DerivedArgList(Args, true); } + +/// TCEToolChain - A tool chain using the llvm bitcode tools to perform +/// all subcommands. See http://tce.cs.tut.fi for our peculiar target. +/// Currently does not support anything else but compilation. + +TCEToolChain::TCEToolChain(const HostInfo &Host, const llvm::Triple& Triple) + : ToolChain(Host, Triple) { + // Path mangling to find libexec + std::string Path(getDriver().Dir); + + Path += "/../libexec"; + getProgramPaths().push_back(Path); +} + +TCEToolChain::~TCEToolChain() { + for (llvm::DenseMap::iterator + it = Tools.begin(), ie = Tools.end(); it != ie; ++it) + delete it->second; +} + +bool TCEToolChain::IsMathErrnoDefault() const { + return true; +} + +bool TCEToolChain::IsUnwindTablesDefault() const { + return false; +} + +const char *TCEToolChain::GetDefaultRelocationModel() const { + return "static"; +} + +const char *TCEToolChain::GetForcedPicModel() const { + return 0; +} + +Tool &TCEToolChain::SelectTool(const Compilation &C, + const JobAction &JA) const { + Action::ActionClass Key; + Key = Action::AnalyzeJobClass; + + Tool *&T = Tools[Key]; + if (!T) { + switch (Key) { + case Action::PreprocessJobClass: + T = new tools::gcc::Preprocess(*this); break; + case Action::AnalyzeJobClass: + T = new tools::Clang(*this); break; + default: + assert(false && "Unsupported action for TCE target."); + } + } + return *T; +} + +DerivedArgList *TCEToolChain::TranslateArgs(InputArgList &Args, + const char *BoundArch) const { + return new DerivedArgList(Args, true); +} + /// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly. OpenBSD::OpenBSD(const HostInfo &Host, const llvm::Triple& Triple) diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h index fda0875..6dd64de 100644 --- a/lib/Driver/ToolChains.h +++ b/lib/Driver/ToolChains.h @@ -267,6 +267,26 @@ public: }; +/// TCEToolChain - A tool chain using the llvm bitcode tools to perform +/// all subcommands. See http://tce.cs.tut.fi for our peculiar target. +class VISIBILITY_HIDDEN TCEToolChain : public ToolChain { +public: + TCEToolChain(const HostInfo &Host, const llvm::Triple& Triple); + ~TCEToolChain(); + + virtual DerivedArgList *TranslateArgs(InputArgList &Args, + const char *BoundArch) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + bool IsMathErrnoDefault() const; + bool IsUnwindTablesDefault() const; + const char* GetDefaultRelocationModel() const; + const char* GetForcedPicModel() const; + +private: + mutable llvm::DenseMap Tools; + +}; + } // end namespace toolchains } // end namespace driver } // end namespace clang diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index ef14df1..63cf98d 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -36,9 +36,10 @@ using namespace clang; ASTUnit::ASTUnit(bool _MainFileIsAST) - : MainFileIsAST(_MainFileIsAST) { + : MainFileIsAST(_MainFileIsAST), ConcurrencyCheckValue(CheckUnlocked) { } ASTUnit::~ASTUnit() { + ConcurrencyCheckValue = CheckLocked; for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I) TemporaryFiles[I].eraseFromDisk(); } diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp index 09b5b45..702c1d0 100644 --- a/lib/Frontend/CacheTokens.cpp +++ b/lib/Frontend/CacheTokens.cpp @@ -184,9 +184,7 @@ class PTHWriter { /// Emit a token to the PTH file. void EmitToken(const Token& T); - void Emit8(uint32_t V) { - Out << (unsigned char)(V); - } + void Emit8(uint32_t V) { ::Emit8(Out, V); } void Emit16(uint32_t V) { ::Emit16(Out, V); } diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index 34cb9ec..4f972f0 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -566,6 +566,17 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &tripl AddGnuCPlusPlusIncludePaths( "/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4", "i686-pc-linux-gnu", "", "", triple); + + // Gentoo amd64 gcc 4.3.2 + AddGnuCPlusPlusIncludePaths( + "/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.2/include/g++-v4", + "x86_64-pc-linux-gnu", "", "", triple); + + // Gentoo amd64 gcc 4.4.3 + AddGnuCPlusPlusIncludePaths( + "/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4", + "x86_64-pc-linux-gnu", "32", "", triple); + break; case llvm::Triple::FreeBSD: AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2", "", "", "", triple); diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp index a13bccb..378b422 100644 --- a/lib/Frontend/RewriteObjC.cpp +++ b/lib/Frontend/RewriteObjC.cpp @@ -4266,6 +4266,17 @@ void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart, // Insert declaration for the function in which block literal is used. if (CurFunctionDeclToDeclareForBlock && !Blocks.empty()) RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock); + bool RewriteSC = (GlobalVarDecl && + !Blocks.empty() && + GlobalVarDecl->getStorageClass() == VarDecl::Static && + GlobalVarDecl->getType().getCVRQualifiers()); + if (RewriteSC) { + std::string SC(" void __"); + SC += GlobalVarDecl->getNameAsString(); + SC += "() {}"; + InsertText(FunLocStart, SC); + } + // Insert closures that were part of the function. for (unsigned i = 0, count=0; i < Blocks.size(); i++) { CollectBlockDeclRefInfo(Blocks[i]); @@ -4311,6 +4322,21 @@ void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart, BlockByCopyDeclsPtrSet.clear(); ImportedBlockDecls.clear(); } + if (RewriteSC) { + // Must insert any 'const/volatile/static here. Since it has been + // removed as result of rewriting of block literals. + std::string SC; + if (GlobalVarDecl->getStorageClass() == VarDecl::Static) + SC = "static "; + if (GlobalVarDecl->getType().isConstQualified()) + SC += "const "; + if (GlobalVarDecl->getType().isVolatileQualified()) + SC += "volatile "; + if (GlobalVarDecl->getType().isRestrictQualified()) + SC += "restrict "; + InsertText(FunLocStart, SC); + } + Blocks.clear(); InnerDeclRefsCount.clear(); InnerDeclRefs.clear(); diff --git a/lib/Headers/smmintrin.h b/lib/Headers/smmintrin.h new file mode 100644 index 0000000..d91ed1d --- /dev/null +++ b/lib/Headers/smmintrin.h @@ -0,0 +1,130 @@ +/*===---- smmintrin.h - SSE intrinsics -------------------------------------=== +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +* +*===-----------------------------------------------------------------------=== +*/ + +#ifndef _SMMINTRIN_H +#define _SMMINTRIN_H + +#ifndef __SSE4_1__ +#error "SSE4.1 instruction set not enabled" +#else + +#include + +/* Type defines. */ +typedef double __v2df __attribute__ ((__vector_size__ (16))); + +/* SSE4 Rounding macros. */ +#define _MM_FROUND_TO_NEAREST_INT 0x00 +#define _MM_FROUND_TO_NEG_INF 0x01 +#define _MM_FROUND_TO_POS_INF 0x02 +#define _MM_FROUND_TO_ZERO 0x03 +#define _MM_FROUND_CUR_DIRECTION 0x04 + +#define _MM_FROUND_RAISE_EXC 0x00 +#define _MM_FROUND_NO_EXC 0x08 + +#define _MM_FROUND_NINT (_MM_FROUND_RAISE_EXC | _MM_FROUND_TO_NEAREST_INT) +#define _MM_FROUND_FLOOR (_MM_FROUND_RAISE_EXC | _MM_FROUND_TO_NEG_INF) +#define _MM_FROUND_CEIL (_MM_FROUND_RAISE_EXC | _MM_FROUND_TO_POS_INF) +#define _MM_FROUND_TRUNC (_MM_FROUND_RAISE_EXC | _MM_FROUND_TO_ZERO) +#define _MM_FROUND_RINT (_MM_FROUND_RAISE_EXC | _MM_FROUND_CUR_DIRECTION) +#define _MM_FROUND_NEARBYINT (_MM_FROUND_RAISE_EXC | _MM_FROUND_CUR_DIRECTION) + +#define _mm_ceil_ps(X) _mm_round_ps((X), _MM_FROUND_CEIL) +#define _mm_ceil_pd(X) _mm_round_pd((X), _MM_FROUND_CEIL) +#define _mm_ceil_ss(X, Y) _mm_round_ss((X), (Y), _MM_FROUND_CEIL) +#define _mm_ceil_sd(X, Y) _mm_round_sd((X), (Y), _MM_FROUND_CEIL) + +#define _mm_floor_ps(X) _mm_round_ps((X), _MM_FROUND_FLOOR) +#define _mm_floor_pd(X) _mm_round_pd((X), _MM_FROUND_FLOOR) +#define _mm_floor_ss(X, Y) _mm_round_ss((X), (Y), _MM_FROUND_FLOOR) +#define _mm_floor_sd(X, Y) _mm_round_sd((X), (Y), _MM_FROUND_FLOOR) + +/* SSE4 Rounding Intrinsics. */ +static inline __m128 __attribute__((__always_inline__, __nodebug__)) +_mm_round_ps (__m128 __V, const int __M) +{ + return (__m128) __builtin_ia32_roundps ((__v4sf)__V, __M); +} + +static inline __m128 __attribute__((__always_inline__, __nodebug__)) +_mm_round_ss (__m128 __V1, __m128 __V2, const int __M) +{ + return (__m128) __builtin_ia32_roundss ((__v4sf)__V1, (__v4sf)__V2, __M); +} + +static inline __m128d __attribute__((__always_inline__, __nodebug__)) +_mm_round_pd (__m128d __V, const int __M) +{ + return (__m128d) __builtin_ia32_roundpd ((__v2df)__V, __M); +} + +static inline __m128d __attribute__((__always_inline__, __nodebug__)) +_mm_round_sd(__m128d __V1, __m128d __V2, const int __M) +{ + return (__m128d) __builtin_ia32_roundsd ((__v2df)__V1, (__v2df)__V2, __M); +} + +/* SSE4 Packed Blending Intrinsics. */ +static inline __m128d __attribute__((__always_inline__, __nodebug__)) +_mm_blend_pd (__m128d __V1, __m128d __V2, const int __M) +{ + return (__m128d) __builtin_ia32_blendpd ((__v2df)__V1, (__v2df)__V2, __M); +} + +static inline __m128 __attribute__((__always_inline__, __nodebug__)) +_mm_blend_ps (__m128 __V1, __m128 __V2, const int __M) +{ + return (__m128) __builtin_ia32_blendps ((__v4sf)__V1, (__v4sf)__V2, __M); +} + +static inline __m128d __attribute__((__always_inline__, __nodebug__)) +_mm_blendv_pd (__m128d __V1, __m128d __V2, __m128d __M) +{ + return (__m128d) __builtin_ia32_blendvpd ((__v2df)__V1, (__v2df)__V2, + (__v2df)__M); +} + +static inline __m128 __attribute__((__always_inline__, __nodebug__)) +_mm_blendv_ps (__m128 __V1, __m128 __V2, __m128 __M) +{ + return (__m128) __builtin_ia32_blendvps ((__v4sf)__V1, (__v4sf)__V2, + (__v4sf)__M); +} + +static inline __m128i __attribute__((__always_inline__, __nodebug__)) +_mm_blendv_epi8 (__m128i __V1, __m128i __V2, __m128i __M) +{ + return (__m128i) __builtin_ia32_pblendvb128 ((__v16qi)__V1, (__v16qi)__V2, + (__v16qi)__M); +} + +static inline __m128i __attribute__((__always_inline__, __nodebug__)) +_mm_blend_epi16 (__m128i __V1, __m128i __V2, const int __M) +{ + return (__m128i) __builtin_ia32_pblendw128 ((__v8hi)__V1, (__v8hi)__V2, __M); +} + +#endif /* __SSE4_1__ */ + +#endif /* _SMMINTRIN_H */ diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index d60cf08..5fe2ef1 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -505,6 +505,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { .Case("attribute_cf_returns_retained", true) .Case("attribute_ns_returns_not_retained", true) .Case("attribute_ns_returns_retained", true) + .Case("attribute_objc_ivar_unused", true) .Default(false); } diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index efd04e8..a94d07a 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1097,12 +1097,16 @@ public: ImplicitConversionSequence TryObjectArgumentInitialization(QualType FromType, CXXMethodDecl *Method, CXXRecordDecl *ActingContext); - bool PerformObjectArgumentInitialization(Expr *&From, CXXMethodDecl *Method); + bool PerformObjectArgumentInitialization(Expr *&From, + NestedNameSpecifier *Qualifier, + CXXMethodDecl *Method); ImplicitConversionSequence TryContextuallyConvertToBool(Expr *From); bool PerformContextuallyConvertToBool(Expr *&From); - bool PerformObjectMemberConversion(Expr *&From, NamedDecl *Member); + bool PerformObjectMemberConversion(Expr *&From, + NestedNameSpecifier *Qualifier, + NamedDecl *Member); // Members have to be NamespaceDecl* or TranslationUnitDecl*. // TODO: make this is a typesafe union. diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 574b225..0708d41 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -5212,14 +5212,35 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType, AbstractVariableType)) Invalid = true; - // FIXME: Need to test for ability to copy-construct and destroy the - // exception variable. - - // FIXME: Need to check for abstract classes. - VarDecl *ExDecl = VarDecl::Create(Context, CurContext, Loc, Name, ExDeclType, TInfo, VarDecl::None); + if (!Invalid) { + if (const RecordType *RecordTy = ExDeclType->getAs()) { + // C++ [except.handle]p16: + // The object declared in an exception-declaration or, if the + // exception-declaration does not specify a name, a temporary (12.2) is + // copy-initialized (8.5) from the exception object. [...] + // The object is destroyed when the handler exits, after the destruction + // of any automatic objects initialized within the handler. + // + // We just pretend to initialize the object with itself, then make sure + // it can be destroyed later. + InitializedEntity Entity = InitializedEntity::InitializeVariable(ExDecl); + Expr *ExDeclRef = DeclRefExpr::Create(Context, 0, SourceRange(), ExDecl, + Loc, ExDeclType, 0); + InitializationKind Kind = InitializationKind::CreateCopy(Loc, + SourceLocation()); + InitializationSequence InitSeq(*this, Entity, Kind, &ExDeclRef, 1); + OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, (void**)&ExDeclRef, 1)); + if (Result.isInvalid()) + Invalid = true; + else + FinalizeVarWithDestructor(ExDecl, RecordTy); + } + } + if (Invalid) ExDecl->setInvalidDecl(); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index d9464ad..10001c3 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -635,7 +635,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, MemberType = Context.getQualifiedType(MemberType, NewQuals); MarkDeclarationReferenced(Loc, *FI); - PerformObjectMemberConversion(Result, *FI); + PerformObjectMemberConversion(Result, /*FIXME:Qualifier=*/0, *FI); // FIXME: Might this end up being a qualified name? Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI, OpLoc, MemberType); @@ -1357,29 +1357,111 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, /// \brief Cast member's object to its own class if necessary. bool -Sema::PerformObjectMemberConversion(Expr *&From, NamedDecl *Member) { - if (FieldDecl *FD = dyn_cast(Member)) - if (CXXRecordDecl *RD = - dyn_cast(FD->getDeclContext())) { - QualType DestType = - Context.getCanonicalType(Context.getTypeDeclType(RD)); - if (DestType->isDependentType() || From->getType()->isDependentType()) - return false; - QualType FromRecordType = From->getType(); - QualType DestRecordType = DestType; - if (FromRecordType->getAs()) { - DestType = Context.getPointerType(DestType); - FromRecordType = FromRecordType->getPointeeType(); - } - if (!Context.hasSameUnqualifiedType(FromRecordType, DestRecordType) && - CheckDerivedToBaseConversion(FromRecordType, - DestRecordType, - From->getSourceRange().getBegin(), - From->getSourceRange())) - return true; - ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase, - /*isLvalue=*/true); +Sema::PerformObjectMemberConversion(Expr *&From, + NestedNameSpecifier *Qualifier, + NamedDecl *Member) { + CXXRecordDecl *RD = dyn_cast(Member->getDeclContext()); + if (!RD) + return false; + + QualType DestRecordType; + QualType DestType; + QualType FromRecordType; + QualType FromType = From->getType(); + bool PointerConversions = false; + if (isa(Member)) { + DestRecordType = Context.getCanonicalType(Context.getTypeDeclType(RD)); + + if (FromType->getAs()) { + DestType = Context.getPointerType(DestRecordType); + FromRecordType = FromType->getPointeeType(); + PointerConversions = true; + } else { + DestType = DestRecordType; + FromRecordType = FromType; } + } else if (CXXMethodDecl *Method = dyn_cast(Member)) { + if (Method->isStatic()) + return false; + + DestType = Method->getThisType(Context); + DestRecordType = DestType->getPointeeType(); + + if (FromType->getAs()) { + FromRecordType = FromType->getPointeeType(); + PointerConversions = true; + } else { + FromRecordType = FromType; + DestType = DestRecordType; + } + } else { + // No conversion necessary. + return false; + } + + if (DestType->isDependentType() || FromType->isDependentType()) + return false; + + // If the unqualified types are the same, no conversion is necessary. + if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType)) + return false; + + // C++ [class.member.lookup]p8: + // [...] Ambiguities can often be resolved by qualifying a name with its + // class name. + // + // If the member was a qualified name and the qualified referred to a + // specific base subobject type, we'll cast to that intermediate type + // first and then to the object in which the member is declared. That allows + // one to resolve ambiguities in, e.g., a diamond-shaped hierarchy such as: + // + // class Base { public: int x; }; + // class Derived1 : public Base { }; + // class Derived2 : public Base { }; + // class VeryDerived : public Derived1, public Derived2 { void f(); }; + // + // void VeryDerived::f() { + // x = 17; // error: ambiguous base subobjects + // Derived1::x = 17; // okay, pick the Base subobject of Derived1 + // } + QualType IntermediateRecordType; + QualType IntermediateType; + if (Qualifier) { + if (const RecordType *IntermediateRecord + = Qualifier->getAsType()->getAs()) { + IntermediateRecordType = QualType(IntermediateRecord, 0); + IntermediateType = IntermediateRecordType; + if (PointerConversions) + IntermediateType = Context.getPointerType(IntermediateType); + } + } + + if (!IntermediateType.isNull() && + IsDerivedFrom(FromRecordType, IntermediateRecordType) && + IsDerivedFrom(IntermediateRecordType, DestRecordType)) { + if (CheckDerivedToBaseConversion(FromRecordType, IntermediateRecordType, + From->getSourceRange().getBegin(), + From->getSourceRange()) || + CheckDerivedToBaseConversion(IntermediateRecordType, DestRecordType, + From->getSourceRange().getBegin(), + From->getSourceRange())) + return true; + + ImpCastExprToType(From, IntermediateType, CastExpr::CK_DerivedToBase, + /*isLvalue=*/!PointerConversions); + ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase, + /*isLvalue=*/!PointerConversions); + return false; + } + + if (CheckDerivedToBaseConversion(FromRecordType, + DestRecordType, + From->getSourceRange().getBegin(), + From->getSourceRange())) + return true; + + ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase, + /*isLvalue=*/true); return false; } @@ -1609,7 +1691,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, return ExprError(); } - if (VD->getType()->isArrayType()) { + if (VD->getType()->isArrayType() && !VD->hasAttr()) { Diag(Loc, diag::err_ref_array_type); Diag(D->getLocation(), diag::note_declared_at); return ExprError(); @@ -2666,7 +2748,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType, } MarkDeclarationReferenced(MemberLoc, FD); - if (PerformObjectMemberConversion(BaseExpr, FD)) + if (PerformObjectMemberConversion(BaseExpr, Qualifier, FD)) return ExprError(); return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, FD, MemberLoc, MemberType)); @@ -6651,7 +6733,7 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, Res = BuildAnonymousStructUnionMemberReference( OC.LocEnd, MemberDecl, Res, OC.LocEnd).takeAs(); } else { - PerformObjectMemberConversion(Res, MemberDecl); + PerformObjectMemberConversion(Res, /*Qualifier=*/0, MemberDecl); // MemberDecl->getType() doesn't get the right qualifiers, but it // doesn't matter here. Res = new (Context) MemberExpr(Res, false, MemberDecl, OC.LocEnd, diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 5f46019..309da29 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2881,7 +2881,7 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp, CXXMethodDecl *Method) { - if (PerformObjectArgumentInitialization(Exp, Method)) + if (PerformObjectArgumentInitialization(Exp, /*Qualifier=*/0, Method)) assert(0 && "Calling BuildCXXMemberCallExpr with invalid call?"); MemberExpr *ME = diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 0f8107a..bf9f73c 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -3365,7 +3365,8 @@ InitializationSequence::Perform(Sema &S, // FIXME: Should we move this initialization into a separate // derived-to-base conversion? I believe the answer is "no", because // we don't want to turn off access control here for c-style casts. - if (S.PerformObjectArgumentInitialization(CurInitExpr, Conversion)) + if (S.PerformObjectArgumentInitialization(CurInitExpr, /*Qualifier=*/0, + Conversion)) return S.ExprError(); // Do a little dance to make sure that CurInit has the proper diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index ed0d137..ff59fc3 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -1282,8 +1282,8 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, QualType FromPointeeType = FromPtrType->getPointeeType(), ToPointeeType = ToPtrType->getPointeeType(); - if (FromPointeeType->isRecordType() && - ToPointeeType->isRecordType()) { + if (FromPointeeType->isRecordType() && ToPointeeType->isRecordType() && + !Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType)) { // We must have a derived-to-base conversion. Check an // ambiguous or inaccessible conversion. if (CheckDerivedToBaseConversion(FromPointeeType, ToPointeeType, @@ -2304,7 +2304,9 @@ Sema::TryObjectArgumentInitialization(QualType OrigFromType, /// the implicit object parameter for the given Method with the given /// expression. bool -Sema::PerformObjectArgumentInitialization(Expr *&From, CXXMethodDecl *Method) { +Sema::PerformObjectArgumentInitialization(Expr *&From, + NestedNameSpecifier *Qualifier, + CXXMethodDecl *Method) { QualType FromRecordType, DestType; QualType ImplicitParamRecordType = Method->getThisType(Context)->getAs()->getPointeeType(); @@ -2327,15 +2329,12 @@ Sema::PerformObjectArgumentInitialization(Expr *&From, CXXMethodDecl *Method) { diag::err_implicit_object_parameter_init) << ImplicitParamRecordType << FromRecordType << From->getSourceRange(); - if (ICS.Standard.Second == ICK_Derived_To_Base && - CheckDerivedToBaseConversion(FromRecordType, - ImplicitParamRecordType, - From->getSourceRange().getBegin(), - From->getSourceRange())) - return true; + if (ICS.Standard.Second == ICK_Derived_To_Base) + return PerformObjectMemberConversion(From, Qualifier, Method); - ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase, - /*isLvalue=*/true); + if (!Context.hasSameType(From->getType(), DestType)) + ImpCastExprToType(From, DestType, CastExpr::CK_NoOp, + /*isLvalue=*/!From->getType()->getAs()); return false; } @@ -5545,7 +5544,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, if (CXXMethodDecl *Method = dyn_cast(FnDecl)) { CheckMemberOperatorAccess(OpLoc, Args[0], Method, Best->getAccess()); - if (PerformObjectArgumentInitialization(Input, Method)) + if (PerformObjectArgumentInitialization(Input, /*Qualifier=*/0, Method)) return ExprError(); } else { // Convert the arguments. @@ -5738,7 +5737,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, if (Arg1.isInvalid()) return ExprError(); - if (PerformObjectArgumentInitialization(Args[0], Method)) + if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, + Method)) return ExprError(); Args[1] = RHS = Arg1.takeAs(); @@ -5904,7 +5904,8 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // Convert the arguments. CXXMethodDecl *Method = cast(FnDecl); - if (PerformObjectArgumentInitialization(Args[0], Method)) + if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, + Method)) return ExprError(); // Convert the arguments. @@ -6009,12 +6010,15 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, MemberExpr *MemExpr; CXXMethodDecl *Method = 0; + NestedNameSpecifier *Qualifier = 0; if (isa(NakedMemExpr)) { MemExpr = cast(NakedMemExpr); Method = cast(MemExpr->getMemberDecl()); + Qualifier = MemExpr->getQualifier(); } else { UnresolvedMemberExpr *UnresExpr = cast(NakedMemExpr); - + Qualifier = UnresExpr->getQualifier(); + QualType ObjectType = UnresExpr->getBaseType(); // Add overload candidates @@ -6113,7 +6117,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, // Convert the object argument (for a non-static member function call). Expr *ObjectArg = MemExpr->getBase(); if (!Method->isStatic() && - PerformObjectArgumentInitialization(ObjectArg, Method)) + PerformObjectArgumentInitialization(ObjectArg, Qualifier, Method)) return ExprError(); MemExpr->setBase(ObjectArg); @@ -6333,7 +6337,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, bool IsError = false; // Initialize the implicit object parameter. - IsError |= PerformObjectArgumentInitialization(Object, Method); + IsError |= PerformObjectArgumentInitialization(Object, /*Qualifier=*/0, + Method); TheCall->setArg(0, Object); @@ -6458,7 +6463,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { // Convert the object parameter. CXXMethodDecl *Method = cast(Best->Function); - if (PerformObjectArgumentInitialization(Base, Method)) + if (PerformObjectArgumentInitialization(Base, /*Qualifier=*/0, Method)) return ExprError(); // No concerns about early exits now. diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 2fb5c84..a79853a 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1034,7 +1034,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, const ObjCInterfaceType *OIT = T->getAs(); T = Context.getObjCObjectPointerType(T, (ObjCProtocolDecl **)OIT->qual_begin(), - OIT->getNumProtocols()); + OIT->getNumProtocols(), + DeclType.Ptr.TypeQuals); break; } T = BuildPointerType(T, DeclType.Ptr.TypeQuals, DeclType.Loc, Name); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 2f3c482..24ea62c 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -969,7 +969,7 @@ public: assert(!Qualifier && "Can't have an unnamed field with a qualifier!"); Expr *BaseExpr = Base.takeAs(); - if (getSema().PerformObjectMemberConversion(BaseExpr, Member)) + if (getSema().PerformObjectMemberConversion(BaseExpr, Qualifier, Member)) return getSema().ExprError(); MemberExpr *ME = -- cgit v1.1