diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-04-03 07:51:34 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-04-03 07:51:34 +0000 |
commit | ac616af773f5062edaaf1a0bb5610b49a22ac41f (patch) | |
tree | 1e9c2f464daf7966d11aa31cf069fa1bc63fdb21 | |
parent | 07b2cfcdb817cc0790420f159a313d61e7241cb9 (diff) | |
download | FreeBSD-src-ac616af773f5062edaaf1a0bb5610b49a22ac41f.zip FreeBSD-src-ac616af773f5062edaaf1a0bb5610b49a22ac41f.tar.gz |
Update clang to r100285.
37 files changed, 530 insertions, 322 deletions
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index a1f5653..9b2b609 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -624,17 +624,23 @@ public: }; private: - ObjCIvarDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation L, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW) : FieldDecl(ObjCIvar, DC, L, Id, T, TInfo, BW, /*Mutable=*/false), DeclAccess(ac) {} public: - static ObjCIvarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, + static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC, + SourceLocation L, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW = NULL); + /// \brief Return the class interface that this ivar is logically contained + /// in; this is either the interface where the ivar was declared, or the + /// interface the ivar is conceptually a part of in the case of synthesized + /// ivars. + const ObjCInterfaceDecl *getContainingInterface() const; + void setAccessControl(AccessControl ac) { DeclAccess = ac; } AccessControl getAccessControl() const { return AccessControl(DeclAccess); } diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 507a61c..a687ee5 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -322,6 +322,15 @@ public: /// the expression is a default argument. bool isDefaultArgument() const; + /// \brief Determine whether this expression directly creates a + /// temporary object (of class type). + bool isTemporaryObject() const { return getTemporaryObject() != 0; } + + /// \brief If this expression directly creates a temporary object of + /// class type, return the expression that actually constructs that + /// temporary object. + const Expr *getTemporaryObject() const; + const Expr* IgnoreParens() const { return const_cast<Expr*>(this)->IgnoreParens(); } diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index facf15f..3e0956f 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -182,6 +182,8 @@ def err_unexected_colon_in_nested_name_spec : Error< "unexpected ':' in nested name specifier">; /// Objective-C parser diagnostics +def err_expected_minus_or_plus : Error< + "method type specifier must start with '-' or '+'">; def err_objc_no_attributes_on_category : Error< "attributes may not be specified on a category">; def err_objc_missing_end : Error<"missing @end">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index be00972..b66d6cc 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -256,6 +256,10 @@ def warn_property_attribute : Warning< def warn_property_types_are_incompatible : Warning< "property type %0 is incompatible with type %1 inherited from %2">; def err_undef_interface : Error<"cannot find interface declaration for %0">; +def err_class_extension_after_impl : Error< + "cannot declare class extension for %0 after class implementation">; +def note_implementation_declared : Note< + "class implementation is declared here">; def warn_dup_category_def : Warning< "duplicate definition of category %1 on interface %0">; def err_conflicting_super_class : Error<"conflicting super class name %0">; diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index d088be0..ed68d68 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -431,6 +431,7 @@ def mno_sse4_1 : Flag<"-mno-sse4.1">, Group<m_x86_Features_Group>; def mno_sse4_2 : Flag<"-mno-sse4.2">, Group<m_x86_Features_Group>; def mno_sse : Flag<"-mno-sse">, Group<m_x86_Features_Group>; def mno_ssse3 : Flag<"-mno-ssse3">, Group<m_x86_Features_Group>; +def mno_aes : Flag<"-mno-aes">, Group<m_x86_Features_Group>; def mno_thumb : Flag<"-mno-thumb">, Group<m_Group>; def marm : Flag<"-marm">, Alias<mno_thumb>; @@ -447,6 +448,7 @@ def msse4_1 : Flag<"-msse4.1">, Group<m_x86_Features_Group>; def msse4_2 : Flag<"-msse4.2">, Group<m_x86_Features_Group>; def msse : Flag<"-msse">, Group<m_x86_Features_Group>; def mssse3 : Flag<"-mssse3">, Group<m_x86_Features_Group>; +def maes : Flag<"-maes">, Group<m_x86_Features_Group>; def mthumb : Flag<"-mthumb">, Group<m_Group>; def mtune_EQ : Joined<"-mtune=">, Group<m_Group>; def multi__module : Flag<"-multi_module">; diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 75cf138..f7d08e8 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -2013,7 +2013,8 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { if (!BitWidth && D->getBitWidth()) return 0; - ObjCIvarDecl *ToIvar = ObjCIvarDecl::Create(Importer.getToContext(), DC, + ObjCIvarDecl *ToIvar = ObjCIvarDecl::Create(Importer.getToContext(), + cast<ObjCContainerDecl>(DC), Loc, Name.getAsIdentifierInfo(), T, TInfo, D->getAccessControl(), BitWidth); diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index ab6b9e1..821e38b 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -561,14 +561,53 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto, // ObjCIvarDecl //===----------------------------------------------------------------------===// -ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, DeclContext *DC, +ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC, SourceLocation L, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW) { + if (DC) { + // Ivar's can only appear in interfaces, implementations (via synthesized + // properties), and class extensions (via direct declaration, or synthesized + // properties). + // + // FIXME: This should really be asserting this: + // (isa<ObjCCategoryDecl>(DC) && + // cast<ObjCCategoryDecl>(DC)->IsClassExtension())) + // but unfortunately we sometimes place ivars into non-class extension + // categories on error. This breaks an AST invariant, and should not be + // fixed. + assert((isa<ObjCInterfaceDecl>(DC) || isa<ObjCImplementationDecl>(DC) || + isa<ObjCCategoryDecl>(DC)) && + "Invalid ivar decl context!"); + } + return new (C) ObjCIvarDecl(DC, L, Id, T, TInfo, ac, BW); } +const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const { + const ObjCContainerDecl *DC = cast<ObjCContainerDecl>(getDeclContext()); + + switch (DC->getKind()) { + default: + case ObjCCategoryImpl: + case ObjCProtocol: + assert(0 && "invalid ivar container!"); + return 0; + // Ivars can only appear in class extension categories. + case ObjCCategory: { + const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(DC); + assert(CD->IsClassExtension() && "invalid container for ivar!"); + return CD->getClassInterface(); + } + + case ObjCImplementation: + return cast<ObjCImplementationDecl>(DC)->getClassInterface(); + + case ObjCInterface: + return cast<ObjCInterfaceDecl>(DC); + } +} //===----------------------------------------------------------------------===// // ObjCAtDefsFieldDecl diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 6764612..ae4bc8c 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1476,6 +1476,71 @@ bool Expr::isDefaultArgument() const { return isa<CXXDefaultArgExpr>(E); } +/// \brief Skip over any no-op casts and any temporary-binding +/// expressions. +static const Expr *skipTemporaryBindingsAndNoOpCasts(const Expr *E) { + while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { + if (ICE->getCastKind() == CastExpr::CK_NoOp) + E = ICE->getSubExpr(); + else + break; + } + + while (const CXXBindTemporaryExpr *BE = dyn_cast<CXXBindTemporaryExpr>(E)) + E = BE->getSubExpr(); + + while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { + if (ICE->getCastKind() == CastExpr::CK_NoOp) + E = ICE->getSubExpr(); + else + break; + } + + return E; +} + +const Expr *Expr::getTemporaryObject() const { + const Expr *E = skipTemporaryBindingsAndNoOpCasts(this); + + // A cast can produce a temporary object. The object's construction + // is represented as a CXXConstructExpr. + if (const CastExpr *Cast = dyn_cast<CastExpr>(E)) { + // Only user-defined and constructor conversions can produce + // temporary objects. + if (Cast->getCastKind() != CastExpr::CK_ConstructorConversion && + Cast->getCastKind() != CastExpr::CK_UserDefinedConversion) + return 0; + + // Strip off temporary bindings and no-op casts. + const Expr *Sub = skipTemporaryBindingsAndNoOpCasts(Cast->getSubExpr()); + + // If this is a constructor conversion, see if we have an object + // construction. + if (Cast->getCastKind() == CastExpr::CK_ConstructorConversion) + return dyn_cast<CXXConstructExpr>(Sub); + + // If this is a user-defined conversion, see if we have a call to + // a function that itself returns a temporary object. + if (Cast->getCastKind() == CastExpr::CK_UserDefinedConversion) + if (const CallExpr *CE = dyn_cast<CallExpr>(Sub)) + if (CE->getCallReturnType()->isRecordType()) + return CE; + + return 0; + } + + // A call returning a class type returns a temporary. + if (const CallExpr *CE = dyn_cast<CallExpr>(E)) { + if (CE->getCallReturnType()->isRecordType()) + return CE; + + return 0; + } + + // Explicit temporary object constructors create temporaries. + return dyn_cast<CXXTemporaryObjectExpr>(E); +} + /// hasAnyTypeDependentArguments - Determines if any of the expressions /// in Exprs is type-dependent. bool Expr::hasAnyTypeDependentArguments(Expr** Exprs, unsigned NumExprs) { diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index e3d9ed3..1797804 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -765,9 +765,12 @@ class X86TargetInfo : public TargetInfo { NoAMD3DNow, AMD3DNow, AMD3DNowAthlon } AMD3DNowLevel; + bool HasAES; + public: X86TargetInfo(const std::string& triple) - : TargetInfo(triple), SSELevel(NoMMXSSE), AMD3DNowLevel(NoAMD3DNow) { + : TargetInfo(triple), SSELevel(NoMMXSSE), AMD3DNowLevel(NoAMD3DNow), + HasAES(false) { LongDoubleFormat = &llvm::APFloat::x87DoubleExtended; } virtual void getTargetBuiltins(const Builtin::Info *&Records, @@ -813,6 +816,7 @@ void X86TargetInfo::getDefaultFeatures(const std::string &CPU, Features["ssse3"] = false; Features["sse41"] = false; Features["sse42"] = false; + Features["aes"] = false; // LLVM does not currently recognize this. // Features["sse4a"] = false; @@ -841,8 +845,10 @@ void X86TargetInfo::getDefaultFeatures(const std::string &CPU, Features["sse42"] = false; } else if (CPU == "atom") setFeatureEnabled(Features, "sse3", true); - else if (CPU == "corei7") + else if (CPU == "corei7") { setFeatureEnabled(Features, "sse4", true); + setFeatureEnabled(Features, "aes", true); + } else if (CPU == "k6" || CPU == "winchip-c6") setFeatureEnabled(Features, "mmx", true); else if (CPU == "k6-2" || CPU == "k6-3" || CPU == "athlon" || @@ -892,6 +898,8 @@ bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, Features["3dnowa"] = true; else if (Name == "3dnowa") Features["3dnow"] = Features["3dnowa"] = true; + else if (Name == "aes") + Features["aes"] = true; } else { if (Name == "mmx") Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = @@ -917,6 +925,8 @@ bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, Features["3dnow"] = Features["3dnowa"] = false; else if (Name == "3dnowa") Features["3dnowa"] = false; + else if (Name == "aes") + Features["aes"] = false; } return true; @@ -931,6 +941,11 @@ void X86TargetInfo::HandleTargetFeatures(std::vector<std::string> &Features) { if (Features[i][0] == '-') continue; + if (Features[i].substr(1) == "aes") { + HasAES = true; + continue; + } + assert(Features[i][0] == '+' && "Invalid target feature!"); X86SSEEnum Level = llvm::StringSwitch<X86SSEEnum>(Features[i].substr(1)) .Case("sse42", SSE42) @@ -969,6 +984,9 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, DefineStd(Builder, "i386", Opts); } + if (HasAES) + Builder.defineMacro("__AES__"); + // Target properties. Builder.defineMacro("__LITTLE_ENDIAN__"); diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 58acd3c..4f14f94 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -1390,9 +1390,9 @@ void CGDebugInfo::EmitStopPoint(llvm::Function *Fn, CGBuilderTy &Builder) { PresumedLoc PLoc = SM.getPresumedLoc(CurLoc); llvm::MDNode *Scope = RegionStack.back(); - Builder.SetCurrentDebugLocation(llvm::NewDebugLoc::get(PLoc.getLine(), - PLoc.getColumn(), - Scope)); + Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(PLoc.getLine(), + PLoc.getColumn(), + Scope)); } /// EmitRegionStart- Constructs the debug code for entering a declarative @@ -1596,7 +1596,7 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertBlock()); llvm::MDNode *Scope = RegionStack.back(); - Call->setDebugLoc(llvm::NewDebugLoc::get(Line, Column, Scope)); + Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope)); } /// EmitDeclare - Emit local variable declaration debug info. @@ -1660,7 +1660,7 @@ void CGDebugInfo::EmitDeclare(const BlockDeclRefExpr *BDRE, unsigned Tag, DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertBlock()); llvm::MDNode *Scope = RegionStack.back(); - Call->setDebugLoc(llvm::NewDebugLoc::get(Line, PLoc.getColumn(), Scope)); + Call->setDebugLoc(llvm::DebugLoc::get(Line, PLoc.getColumn(), Scope)); } void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD, diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index d9585c9..1fd1da8 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -307,23 +307,7 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest, // Code gen optimization to eliminate copy constructor and return // its first argument instead. if (getContext().getLangOptions().ElideConstructors && E->isElidable()) { - const Expr *Arg = E->getArg(0); - - if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) { - assert((ICE->getCastKind() == CastExpr::CK_NoOp || - ICE->getCastKind() == CastExpr::CK_ConstructorConversion || - ICE->getCastKind() == CastExpr::CK_UserDefinedConversion) && - "Unknown implicit cast kind in constructor elision"); - Arg = ICE->getSubExpr(); - } - - if (const CXXFunctionalCastExpr *FCE = dyn_cast<CXXFunctionalCastExpr>(Arg)) - Arg = FCE->getSubExpr(); - - if (const CXXBindTemporaryExpr *BindExpr = - dyn_cast<CXXBindTemporaryExpr>(Arg)) - Arg = BindExpr->getSubExpr(); - + const Expr *Arg = E->getArg(0)->getTemporaryObject(); EmitAggExpr(Arg, Dest, false); return; } diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 883ed98..5373390 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -42,41 +42,15 @@ using namespace CodeGen; // don't belong in CGObjCRuntime either so we will live with it for // now. -/// FindIvarInterface - Find the interface containing the ivar. -/// -/// FIXME: We shouldn't need to do this, the containing context should -/// be fixed. -static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context, - const ObjCInterfaceDecl *OID, - const ObjCIvarDecl *OIVD, - unsigned &Index) { - // FIXME: The index here is closely tied to how - // ASTContext::getObjCLayout is implemented. This should be fixed to - // get the information from the layout directly. - Index = 0; - llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; - Context.ShallowCollectObjCIvars(OID, Ivars); - for (unsigned k = 0, e = Ivars.size(); k != e; ++k) { - if (OIVD == Ivars[k]) - return OID; - ++Index; - } - - // Otherwise check in the super class. - if (const ObjCInterfaceDecl *Super = OID->getSuperClass()) - return FindIvarInterface(Context, Super, OIVD, Index); - - return 0; -} - static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM, const ObjCInterfaceDecl *OID, const ObjCImplementationDecl *ID, const ObjCIvarDecl *Ivar) { - unsigned Index; - const ObjCInterfaceDecl *Container = - FindIvarInterface(CGM.getContext(), OID, Ivar, Index); - assert(Container && "Unable to find ivar container"); + const ObjCInterfaceDecl *Container = Ivar->getContainingInterface(); + + // FIXME: We should eliminate the need to have ObjCImplementationDecl passed + // in here; it should never be necessary because that should be the lexical + // decl context for the ivar. // If we know have an implementation (and the ivar is in it) then // look up in the implementation layout. @@ -85,6 +59,22 @@ static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM, RL = &CGM.getContext().getASTObjCImplementationLayout(ID); else RL = &CGM.getContext().getASTObjCInterfaceLayout(Container); + + // Compute field index. + // + // FIXME: The index here is closely tied to how ASTContext::getObjCLayout is + // implemented. This should be fixed to get the information from the layout + // directly. + unsigned Index = 0; + llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; + CGM.getContext().ShallowCollectObjCIvars(Container, Ivars); + for (unsigned k = 0, e = Ivars.size(); k != e; ++k) { + if (Ivar == Ivars[k]) + break; + ++Index; + } + assert(Index != Ivars.size() && "Ivar is not inside container!"); + return RL->getFieldOffset(Index); } @@ -4727,14 +4717,10 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name, /// ObjCIvarOffsetVariable - Returns the ivar offset variable for /// the given ivar. -llvm::GlobalVariable * CGObjCNonFragileABIMac::ObjCIvarOffsetVariable( - const ObjCInterfaceDecl *ID, - const ObjCIvarDecl *Ivar) { - // FIXME: We shouldn't need to do this lookup. - unsigned Index; - const ObjCInterfaceDecl *Container = - FindIvarInterface(CGM.getContext(), ID, Ivar, Index); - assert(Container && "Unable to find ivar container!"); +llvm::GlobalVariable * +CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID, + const ObjCIvarDecl *Ivar) { + const ObjCInterfaceDecl *Container = Ivar->getContainingInterface(); std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() + '.' + Ivar->getNameAsString(); llvm::GlobalVariable *IvarOffsetGV = @@ -4749,10 +4735,10 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::ObjCIvarOffsetVariable( return IvarOffsetGV; } -llvm::Constant * CGObjCNonFragileABIMac::EmitIvarOffsetVar( - const ObjCInterfaceDecl *ID, - const ObjCIvarDecl *Ivar, - unsigned long int Offset) { +llvm::Constant * +CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID, + const ObjCIvarDecl *Ivar, + unsigned long int Offset) { llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar); IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy, Offset)); diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 2d1c734..fc6d1a8 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -3146,11 +3146,16 @@ void CodeGenVTables::EmitVTableRelatedData(GlobalDecl GD) { if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl()) return; } else { + // If we have no key funcion and this is a explicit instantiation declaration, + // we will produce a vtable at the explicit instantiation. We don't need one + // here. + if (RDKind == clang::TSK_ExplicitInstantiationDeclaration) + return; + // If this is an explicit instantiation of a method, we don't need a vtable. // Since we have no key function, we will emit the vtable when we see // a use, and just defining a function is not an use. - if ((RDKind == TSK_ImplicitInstantiation || - RDKind == TSK_ExplicitInstantiationDeclaration) && + if (RDKind == TSK_ImplicitInstantiation && MDKind == TSK_ExplicitInstantiationDefinition) return; } diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 9a3473f..243be0e 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -142,12 +142,11 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration( // We have a class or category name - consume it. IdentifierInfo *nameId = Tok.getIdentifierInfo(); SourceLocation nameLoc = ConsumeToken(); - + bool Err = false; if (Tok.is(tok::l_paren)) { // we have a category. SourceLocation lparenLoc = ConsumeParen(); SourceLocation categoryLoc, rparenLoc; IdentifierInfo *categoryId = 0; - if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCInterfaceCategory(CurScope, nameId); ConsumeToken(); @@ -157,7 +156,14 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration( if (Tok.is(tok::identifier)) { categoryId = Tok.getIdentifierInfo(); categoryLoc = ConsumeToken(); - } else if (!getLang().ObjC2) { + } + else if (isKnownToBeTypeSpecifier(Tok)) { + // Fall thru after diagnosing for better error recovery. + Diag(Tok, diag::err_expected_minus_or_plus); + ConsumeToken(); + Err = true; + } + else if (!getLang().ObjC2) { Diag(Tok, diag::err_expected_ident); // missing category name. return DeclPtrTy(); } @@ -167,33 +173,34 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration( return DeclPtrTy(); } rparenLoc = ConsumeParen(); - - // Next, we need to check for any protocol references. - SourceLocation LAngleLoc, EndProtoLoc; - llvm::SmallVector<DeclPtrTy, 8> ProtocolRefs; - llvm::SmallVector<SourceLocation, 8> ProtocolLocs; - if (Tok.is(tok::less) && - ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, + if (!Err) { + // Next, we need to check for any protocol references. + SourceLocation LAngleLoc, EndProtoLoc; + llvm::SmallVector<DeclPtrTy, 8> ProtocolRefs; + llvm::SmallVector<SourceLocation, 8> ProtocolLocs; + if (Tok.is(tok::less) && + ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, LAngleLoc, EndProtoLoc)) - return DeclPtrTy(); + return DeclPtrTy(); - if (attrList) // categories don't support attributes. - Diag(Tok, diag::err_objc_no_attributes_on_category); - - DeclPtrTy CategoryType = - Actions.ActOnStartCategoryInterface(atLoc, - nameId, nameLoc, - categoryId, categoryLoc, - ProtocolRefs.data(), - ProtocolRefs.size(), - ProtocolLocs.data(), - EndProtoLoc); - if (Tok.is(tok::l_brace)) + if (attrList) // categories don't support attributes. + Diag(Tok, diag::err_objc_no_attributes_on_category); + + DeclPtrTy CategoryType = + Actions.ActOnStartCategoryInterface(atLoc, + nameId, nameLoc, + categoryId, categoryLoc, + ProtocolRefs.data(), + ProtocolRefs.size(), + ProtocolLocs.data(), + EndProtoLoc); + if (Tok.is(tok::l_brace)) ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, atLoc); - ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword); - return CategoryType; + ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword); + return CategoryType; + } } // Parse a class interface. IdentifierInfo *superClassId = 0; @@ -235,7 +242,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration( ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, atLoc); ParseObjCInterfaceDeclList(ClsType, tok::objc_interface); - return ClsType; + return Err ? DeclPtrTy() : ClsType; } /// The Objective-C property callback. This should be defined where @@ -328,7 +335,14 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, "", tok::semi); continue; } - + if (Tok.is(tok::l_paren)) { + Diag(Tok, diag::err_expected_minus_or_plus); + DeclPtrTy methodPrototype = ParseObjCMethodDecl(Tok.getLocation(), + tok::minus, + interfaceDecl, + MethodImplKind); + continue; + } // Ignore excess semicolons. if (Tok.is(tok::semi)) { ConsumeToken(); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index f3d0dcf..541c271 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5740,17 +5740,15 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S, Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility) : ObjCIvarDecl::None; // Must set ivar's DeclContext to its enclosing interface. - Decl *EnclosingDecl = IntfDecl.getAs<Decl>(); - DeclContext *EnclosingContext; + ObjCContainerDecl *EnclosingDecl = IntfDecl.getAs<ObjCContainerDecl>(); + ObjCContainerDecl *EnclosingContext; if (ObjCImplementationDecl *IMPDecl = dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) { // Case of ivar declared in an implementation. Context is that of its class. - ObjCInterfaceDecl* IDecl = IMPDecl->getClassInterface(); - assert(IDecl && "No class- ActOnIvar"); - EnclosingContext = cast_or_null<DeclContext>(IDecl); + EnclosingContext = IMPDecl->getClassInterface(); + assert(EnclosingContext && "Implementation has no class interface!"); } else - EnclosingContext = dyn_cast<DeclContext>(EnclosingDecl); - assert(EnclosingContext && "null DeclContext for ivar - ActOnIvar"); + EnclosingContext = EnclosingDecl; // Construct the decl. ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 47df435..39e3739 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3965,33 +3965,21 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, bool BaseInitialization) { bool Elidable = false; - // C++ [class.copy]p15: - // Whenever a temporary class object is copied using a copy constructor, and - // this object and the copy have the same cv-unqualified type, an - // implementation is permitted to treat the original and the copy as two - // different ways of referring to the same object and not perform a copy at - // all, even if the class copy constructor or destructor have side effects. - - // FIXME: Is this enough? - if (Constructor->isCopyConstructor()) { - Expr *E = ((Expr **)ExprArgs.get())[0]; - if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) - if (ICE->getCastKind() == CastExpr::CK_NoOp) - E = ICE->getSubExpr(); - if (CXXFunctionalCastExpr *FCE = dyn_cast<CXXFunctionalCastExpr>(E)) - E = FCE->getSubExpr(); - while (CXXBindTemporaryExpr *BE = dyn_cast<CXXBindTemporaryExpr>(E)) - E = BE->getSubExpr(); - if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) - if (ICE->getCastKind() == CastExpr::CK_NoOp) - E = ICE->getSubExpr(); - - if (CallExpr *CE = dyn_cast<CallExpr>(E)) - Elidable = !CE->getCallReturnType()->isReferenceType(); - else if (isa<CXXTemporaryObjectExpr>(E)) - Elidable = true; - else if (isa<CXXConstructExpr>(E)) - Elidable = true; + // C++0x [class.copy]p34: + // When certain criteria are met, an implementation is allowed to + // omit the copy/move construction of a class object, even if the + // copy/move constructor and/or destructor for the object have + // side effects. [...] + // - when a temporary class object that has not been bound to a + // reference (12.2) would be copied/moved to a class object + // with the same cv-unqualified type, the copy/move operation + // can be omitted by constructing the temporary object + // directly into the target of the omitted copy/move + if (Constructor->isCopyConstructor() && ExprArgs.size() >= 1) { + Expr *SubExpr = ((Expr **)ExprArgs.get())[0]; + Elidable = SubExpr->isTemporaryObject() && + Context.hasSameUnqualifiedType(SubExpr->getType(), + Context.getTypeDeclType(Constructor->getParent())); } return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor, diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 9bc0846..0c47e63 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -431,6 +431,11 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, // Class extensions require a special treatment. Use an existing one. // Note that 'getClassExtension()' can return NULL. CDecl = IDecl->getClassExtension(); + if (IDecl->getImplementation()) { + Diag(ClassLoc, diag::err_class_extension_after_impl) << ClassName; + Diag(IDecl->getImplementation()->getLocation(), + diag::note_implementation_declared); + } } if (!CDecl) { diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index fbdf080..2dfb954 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1345,11 +1345,6 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, } } } - if (LangOpts.ObjCNonFragileABI2 && LookForIvars && Lookup.empty()) { - ObjCIvarDecl *Ivar = SynthesizeNewPropertyIvar(IFace, II); - if (Ivar) - return LookupInObjCMethod(Lookup, S, II, AllowBuiltinCreation); - } // Sentinel value saying that we didn't do anything special. return Owned((Expr*) 0); } diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 648e43b..1d0575c 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -2583,10 +2583,7 @@ static void TryConstructorInitialization(Sema &S, Expr **Args, unsigned NumArgs, QualType DestType, InitializationSequence &Sequence) { - if (Kind.getKind() == InitializationKind::IK_Copy) - Sequence.setSequenceKind(InitializationSequence::UserDefinedConversion); - else - Sequence.setSequenceKind(InitializationSequence::ConstructorInitialization); + Sequence.setSequenceKind(InitializationSequence::ConstructorInitialization); // Build the candidate set directly in the initialization sequence // structure, so that it will persist if we fail. @@ -2597,7 +2594,7 @@ static void TryConstructorInitialization(Sema &S, // explicit conversion operators. bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct || Kind.getKind() == InitializationKind::IK_Value || - Kind.getKind() == InitializationKind::IK_Default); + Kind.getKind() == InitializationKind::IK_Default); // The type we're converting to is a class type. Enumerate its constructors // to see if one is suitable. @@ -2661,14 +2658,10 @@ static void TryConstructorInitialization(Sema &S, // Add the constructor initialization step. Any cv-qualification conversion is // subsumed by the initialization. - if (Kind.getKind() == InitializationKind::IK_Copy) { - Sequence.AddUserConversionStep(Best->Function, Best->FoundDecl, DestType); - } else { - Sequence.AddConstructorInitializationStep( + Sequence.AddConstructorInitializationStep( cast<CXXConstructorDecl>(Best->Function), Best->FoundDecl.getAccess(), DestType); - } } /// \brief Attempt value initialization (C++ [dcl.init]p7). @@ -3085,14 +3078,11 @@ getAssignmentAction(const InitializedEntity &Entity) { return Sema::AA_Converting; } -static bool shouldBindAsTemporary(const InitializedEntity &Entity, - bool IsCopy) { +static bool shouldBindAsTemporary(const InitializedEntity &Entity) { switch (Entity.getKind()) { - case InitializedEntity::EK_Result: case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_Member: - return !IsCopy; - + case InitializedEntity::EK_Result: case InitializedEntity::EK_New: case InitializedEntity::EK_Variable: case InitializedEntity::EK_Base: @@ -3108,21 +3098,38 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity, llvm_unreachable("missed an InitializedEntity kind?"); } -/// \brief If we need to perform an additional copy of the initialized object -/// for this kind of entity (e.g., the result of a function or an object being -/// thrown), make the copy. -static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S, - const InitializedEntity &Entity, - const InitializationKind &Kind, - Sema::OwningExprResult CurInit) { +static Sema::OwningExprResult CopyObject(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Sema::OwningExprResult CurInit) { + // Determine which class type we're copying. Expr *CurInitExpr = (Expr *)CurInit.get(); - + CXXRecordDecl *Class = 0; + if (const RecordType *Record = CurInitExpr->getType()->getAs<RecordType>()) + Class = cast<CXXRecordDecl>(Record->getDecl()); + if (!Class) + return move(CurInit); + + // C++0x [class.copy]p34: + // When certain criteria are met, an implementation is allowed to + // omit the copy/move construction of a class object, even if the + // copy/move constructor and/or destructor for the object have + // side effects. [...] + // - when a temporary class object that has not been bound to a + // reference (12.2) would be copied/moved to a class object + // with the same cv-unqualified type, the copy/move operation + // can be omitted by constructing the temporary object + // directly into the target of the omitted copy/move + // + // Note that the other three bullets are handled elsewhere. Copy + // elision for return statements and throw expressions are (FIXME: + // not yet) handled as part of constructor initialization, while + // copy elision for exception handlers is handled by the run-time. + bool Elidable = CurInitExpr->isTemporaryObject() && + S.Context.hasSameUnqualifiedType(Entity.getType(), CurInitExpr->getType()); SourceLocation Loc; - switch (Entity.getKind()) { case InitializedEntity::EK_Result: - if (Entity.getType()->isReferenceType()) - return move(CurInit); Loc = Entity.getReturnLoc(); break; @@ -3131,38 +3138,20 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S, break; case InitializedEntity::EK_Variable: - if (Entity.getType()->isReferenceType() || - Kind.getKind() != InitializationKind::IK_Copy) - return move(CurInit); Loc = Entity.getDecl()->getLocation(); break; case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_Member: - if (Entity.getType()->isReferenceType() || - Kind.getKind() != InitializationKind::IK_Copy) - return move(CurInit); - Loc = CurInitExpr->getLocStart(); - break; - case InitializedEntity::EK_Parameter: - // FIXME: Do we need this initialization for a parameter? - return move(CurInit); - - case InitializedEntity::EK_New: case InitializedEntity::EK_Temporary: + case InitializedEntity::EK_New: case InitializedEntity::EK_Base: case InitializedEntity::EK_VectorElement: - // We don't need to copy for any of these initialized entities. - return move(CurInit); + Loc = CurInitExpr->getLocStart(); + break; } - - CXXRecordDecl *Class = 0; - if (const RecordType *Record = CurInitExpr->getType()->getAs<RecordType>()) - Class = cast<CXXRecordDecl>(Record->getDecl()); - if (!Class) - return move(CurInit); - + // Perform overload resolution using the class's copy constructors. DeclarationName ConstructorName = S.Context.DeclarationNames.getCXXConstructorName( @@ -3171,7 +3160,7 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S, OverloadCandidateSet CandidateSet(Loc); for (llvm::tie(Con, ConEnd) = Class->lookup(ConstructorName); Con != ConEnd; ++Con) { - // Find the constructor (which may be a template). + // Only consider copy constructors. CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(*Con); if (!Constructor || Constructor->isInvalidDecl() || !Constructor->isCopyConstructor()) @@ -3181,7 +3170,7 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S, = DeclAccessPair::make(Constructor, Constructor->getAccess()); S.AddOverloadCandidate(Constructor, FoundDecl, &CurInitExpr, 1, CandidateSet); - } + } OverloadCandidateSet::iterator Best; switch (S.BestViableFunction(CandidateSet, Loc, Best)) { @@ -3218,9 +3207,9 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S, Best->FoundDecl.getAccess()); CurInit.release(); - return S.BuildCXXConstructExpr(Loc, CurInitExpr->getType(), + return S.BuildCXXConstructExpr(Loc, Entity.getType().getNonReferenceType(), cast<CXXConstructorDecl>(Best->Function), - /*Elidable=*/true, + Elidable, Sema::MultiExprArg(S, (void**)&CurInitExpr, 1)); } @@ -3474,7 +3463,9 @@ InitializationSequence::Perform(Sema &S, CastKind = CastExpr::CK_UserDefinedConversion; } - if (shouldBindAsTemporary(Entity, IsCopy)) + bool RequiresCopy = !IsCopy && + getKind() != InitializationSequence::ReferenceBinding; + if (RequiresCopy || shouldBindAsTemporary(Entity)) CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>()); CurInitExpr = CurInit.takeAs<Expr>(); @@ -3483,8 +3474,8 @@ InitializationSequence::Perform(Sema &S, CurInitExpr, IsLvalue)); - if (!IsCopy) - CurInit = CopyIfRequiredForEntity(S, Entity, Kind, move(CurInit)); + if (RequiresCopy) + CurInit = CopyObject(S, Entity, Kind, move(CurInit)); break; } @@ -3560,13 +3551,9 @@ InitializationSequence::Perform(Sema &S, S.CheckConstructorAccess(Loc, Constructor, Step->Function.FoundDecl.getAccess()); - bool Elidable - = cast<CXXConstructExpr>((Expr *)CurInit.get())->isElidable(); - if (shouldBindAsTemporary(Entity, Elidable)) + if (shouldBindAsTemporary(Entity)) CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>()); - - if (!Elidable) - CurInit = CopyIfRequiredForEntity(S, Entity, Kind, move(CurInit)); + break; } diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index f815068..52b9bcf 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -281,7 +281,7 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc, DeclPtrTy ClassCatImpDecl, IdentifierInfo *PropertyId, IdentifierInfo *PropertyIvar) { - Decl *ClassImpDecl = ClassCatImpDecl.getAs<Decl>(); + ObjCContainerDecl *ClassImpDecl = ClassCatImpDecl.getAs<ObjCContainerDecl>(); // Make sure we have a context for the property implementation declaration. if (!ClassImpDecl) { Diag(AtLoc, diag::error_missing_property_context); @@ -353,14 +353,11 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc, ObjCInterfaceDecl *ClassDeclared; Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared); if (!Ivar) { - DeclContext *EnclosingContext = cast_or_null<DeclContext>(ClassImpDecl); - assert(EnclosingContext && - "null DeclContext for synthesized ivar - ActOnPropertyImplDecl"); - Ivar = ObjCIvarDecl::Create(Context, EnclosingContext, PropertyLoc, + Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, PropertyLoc, PropertyIvar, PropType, /*Dinfo=*/0, ObjCIvarDecl::Public, (Expr *)0); - EnclosingContext->addDecl(Ivar); + ClassImpDecl->addDecl(Ivar); IDecl->makeDeclVisibleInContext(Ivar, false); property->setPropertyIvarDecl(Ivar); @@ -1072,15 +1069,10 @@ Sema::SynthesizeNewPropertyIvar(ObjCInterfaceDecl *IDecl, ObjCIvarDecl *Ivar = 0; ObjCPropertyDecl *Prop = LookupPropertyDecl(IDecl, NameII); if (Prop && !Prop->isInvalidDecl()) { - DeclContext *EnclosingContext = cast_or_null<DeclContext>(IDecl); QualType PropType = Context.getCanonicalType(Prop->getType()); - assert(EnclosingContext && - "null DeclContext for synthesized ivar - SynthesizeNewPropertyIvar"); - Ivar = ObjCIvarDecl::Create(Context, EnclosingContext, - Prop->getLocation(), - NameII, PropType, /*Dinfo=*/0, - ObjCIvarDecl::Public, - (Expr *)0); + Ivar = ObjCIvarDecl::Create(Context, IDecl, Prop->getLocation(), NameII, + PropType, /*Dinfo=*/0, + ObjCIvarDecl::Public, (Expr *)0); Ivar->setLexicalDeclContext(IDecl); IDecl->addDecl(Ivar); Prop->setPropertyIvarDecl(Ivar); diff --git a/test/CodeGen/enum.c b/test/CodeGen/enum.c index eab32c1..87b0e1e 100644 --- a/test/CodeGen/enum.c +++ b/test/CodeGen/enum.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm-bc -o - | opt -std-compile-opts | llvm-dis | grep 'ret i32 6' -// RUN: %clang_cc1 -triple i386-unknown-unknown -x c++ %s -emit-llvm-bc -o - | opt -std-compile-opts | llvm-dis | grep 'ret i32 7' +// RUN: %clang_cc1 -triple i386-unknown-unknown %s -O3 -emit-llvm -o - | grep 'ret i32 6' +// RUN: %clang_cc1 -triple i386-unknown-unknown -x c++ %s -O3 -emit-llvm -o - | grep 'ret i32 7' static enum { foo, bar = 1U } z; diff --git a/test/CodeGen/indirect-goto.c b/test/CodeGen/indirect-goto.c index 9fd8cfa..7a3d717 100644 --- a/test/CodeGen/indirect-goto.c +++ b/test/CodeGen/indirect-goto.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm-bc -o - %s | opt -std-compile-opts -S | grep "ret i32 2520" +// RUN: %clang_cc1 -triple i386-unknown-unknown -O3 -emit-llvm -o - %s | grep "ret i32 2520" static int foo(unsigned i) { void *addrs[] = { &&L1, &&L2, &&L3, &&L4, &&L5 }; diff --git a/test/CodeGen/rdr-6098585-default-after-caserange.c b/test/CodeGen/rdr-6098585-default-after-caserange.c deleted file mode 100644 index 3a89aa3..0000000 --- a/test/CodeGen/rdr-6098585-default-after-caserange.c +++ /dev/null @@ -1,18 +0,0 @@ -// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t -// RUN: grep "ret i32" %t | count 1 -// RUN: grep "ret i32 10" %t | count 1 - -// Ensure that default after a case range is not ignored. - -static int f1(unsigned x) { - switch(x) { - case 10 ... 0xFFFFFFFF: - return 0; - default: - return 10; - } -} - -int g() { - return f1(2); -} diff --git a/test/CodeGen/rdr-6098585-default-fallthrough-to-caserange.c b/test/CodeGen/rdr-6098585-default-fallthrough-to-caserange.c deleted file mode 100644 index ba41b51..0000000 --- a/test/CodeGen/rdr-6098585-default-fallthrough-to-caserange.c +++ /dev/null @@ -1,20 +0,0 @@ -// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t -// RUN: grep "ret i32 10" %t - -// Ensure that this doesn't compile to infinite loop in g() due to -// miscompilation of fallthrough from default to a (tested) case -// range. - -static int f0(unsigned x) { - switch(x) { - default: - x += 1; - case 10 ... 0xFFFFFFFF: - return 0; - } -} - -int g() { - f0(1); - return 10; -} diff --git a/test/CodeGen/rdr-6098585-empty-case-range.c b/test/CodeGen/rdr-6098585-empty-case-range.c deleted file mode 100644 index 1cf77ac..0000000 --- a/test/CodeGen/rdr-6098585-empty-case-range.c +++ /dev/null @@ -1,23 +0,0 @@ -// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t -// RUN: grep "ret i32" %t | count 2 -// RUN: grep "ret i32 3" %t | count 2 - -// This generated incorrect code because of poor switch chaining. -int f1(int x) { - switch(x) { - default: - return 3; - case 10 ... 0xFFFFFFFF: - return 0; - } -} - -// This just asserted because of the way case ranges were calculated. -int f2(int x) { - switch (x) { - default: - return 3; - case 10 ... -1: - return 0; - } -} diff --git a/test/CodeGen/rdr-6098585-fallthrough-to-empty-range.c b/test/CodeGen/rdr-6098585-fallthrough-to-empty-range.c deleted file mode 100644 index 48a6cc2..0000000 --- a/test/CodeGen/rdr-6098585-fallthrough-to-empty-range.c +++ /dev/null @@ -1,15 +0,0 @@ -// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t -// RUN: grep "ret i32 %" %t - -// Make sure return is not constant (if empty range is skipped or miscompiled) - -int f0(unsigned x) { - switch(x) { - case 2: - // fallthrough empty range - case 10 ... 9: - return 10; - default: - return 0; - } -} diff --git a/test/CodeGen/rdr-6098585-unsigned-caserange.c b/test/CodeGen/rdr-6098585-unsigned-caserange.c deleted file mode 100644 index 6f577df..0000000 --- a/test/CodeGen/rdr-6098585-unsigned-caserange.c +++ /dev/null @@ -1,12 +0,0 @@ -// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t -// RUN: grep "ret i32" %t | count 1 -// RUN: grep "ret i32 3" %t | count 1 - -int f2(unsigned x) { - switch(x) { - default: - return 3; - case 0xFFFFFFFF ... 1: // This range should be empty because x is unsigned. - return 0; - } -} diff --git a/test/CodeGen/switch.c b/test/CodeGen/switch.c index 519ccba..dc2d27b 100644 --- a/test/CodeGen/switch.c +++ b/test/CodeGen/switch.c @@ -100,3 +100,97 @@ void foo7(){ } } + +// CHECK: define i32 @f8( +// CHECK: ret i32 3 +// CHECK: } +int f8(unsigned x) { + switch(x) { + default: + return 3; + case 0xFFFFFFFF ... 1: // This range should be empty because x is unsigned. + return 0; + } +} + +// Ensure that default after a case range is not ignored. +// +// CHECK: define i32 @f9() +// CHECK: ret i32 10 +// CHECK: } +static int f9_0(unsigned x) { + switch(x) { + case 10 ... 0xFFFFFFFF: + return 0; + default: + return 10; + } +} +int f9() { + return f9_0(2); +} + +// Ensure that this doesn't compile to infinite loop in g() due to +// miscompilation of fallthrough from default to a (tested) case +// range. +// +// CHECK: define i32 @f10() +// CHECK: ret i32 10 +// CHECK: } +static int f10_0(unsigned x) { + switch(x) { + default: + x += 1; + case 10 ... 0xFFFFFFFF: + return 0; + } +} + +int f10() { + f10_0(1); + return 10; +} + +// This generated incorrect code because of poor switch chaining. +// +// CHECK: define i32 @f11( +// CHECK: ret i32 3 +// CHECK: } +int f11(int x) { + switch(x) { + default: + return 3; + case 10 ... 0xFFFFFFFF: + return 0; + } +} + +// This just asserted because of the way case ranges were calculated. +// +// CHECK: define i32 @f12( +// CHECK: ret i32 3 +// CHECK: } +int f12(int x) { + switch (x) { + default: + return 3; + case 10 ... -1: + return 0; + } +} + +// Make sure return is not constant (if empty range is skipped or miscompiled) +// +// CHECK: define i32 @f13( +// CHECK: ret i32 % +// CHECK: } +int f13(unsigned x) { + switch(x) { + case 2: + // fallthrough empty range + case 10 ... 9: + return 10; + default: + return 0; + } +} diff --git a/test/CodeGenCXX/copy-initialization.cpp b/test/CodeGenCXX/copy-initialization.cpp new file mode 100644 index 0000000..62b9f26 --- /dev/null +++ b/test/CodeGenCXX/copy-initialization.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s + +struct Foo { + Foo(); + Foo(const Foo&); +}; + +struct Bar { + Bar(); + operator const Foo&() const; +}; + +void f(Foo); + +// CHECK: define void @_Z1g3Foo(%struct.Bar* %foo) +void g(Foo foo) { + // CHECK: call void @_ZN3BarC1Ev + // CHECK: @_ZNK3BarcvRK3FooEv + // CHECK: call void @_Z1f3Foo + f(Bar()); + // CHECK: call void @_ZN3FooC1Ev + // CHECK: call void @_Z1f3Foo + f(Foo()); + // CHECK: call void @_ZN3FooC1ERKS_ + // CHECK: call void @_Z1f3Foo + f(foo); + // CHECK: ret +} + diff --git a/test/CodeGenCXX/derived-to-base-conv.cpp b/test/CodeGenCXX/derived-to-base-conv.cpp index c1a0caa..f2835b7 100644 --- a/test/CodeGenCXX/derived-to-base-conv.cpp +++ b/test/CodeGenCXX/derived-to-base-conv.cpp @@ -7,16 +7,21 @@ extern "C" int printf(...); extern "C" void exit(int); struct A { - A (const A&) { printf("A::A(const A&)\n"); } - A() {}; + A (const A&) { printf("A::A(const A&)\n"); } + A() {}; + ~A() { printf("A::~A()\n"); } }; struct B : public A { B() {}; -}; + B(const B& Other) : A(Other) { printf("B::B(const B&)\n"); } + ~B() { printf("B::~B()\n"); } +}; struct C : public B { C() {}; + C(const C& Other) : B(Other) { printf("C::C(const C&)\n"); } + ~C() { printf("C::~C()\n"); } }; struct X { @@ -24,6 +29,7 @@ struct X { operator C&() {printf("X::operator C&()\n"); return c; } X (const X&) { printf("X::X(const X&)\n"); } X () { printf("X::X()\n"); } + ~X () { printf("X::~X()\n"); } B b; C c; }; diff --git a/test/CodeGenCXX/virt.cpp b/test/CodeGenCXX/virt.cpp index c404129..874ffb1 100644 --- a/test/CodeGenCXX/virt.cpp +++ b/test/CodeGenCXX/virt.cpp @@ -104,7 +104,8 @@ struct test7_B1 : virtual test7_B2 { virtual void funcB1(); }; struct test7_D : test7_B2, virtual test7_B1 { }; -// CHECK-LP64: .zerofill __DATA,__common,_d7,16,3 +// FIXME: we were checking for an alignment of 3 (?) +// CHECK-LP64: .zerofill __DATA,__common,_d7,16, struct test3_B3 { virtual void funcB3(); }; diff --git a/test/CodeGenCXX/vtable-linkage.cpp b/test/CodeGenCXX/vtable-linkage.cpp index a4ea2a1..c75efe2 100644 --- a/test/CodeGenCXX/vtable-linkage.cpp +++ b/test/CodeGenCXX/vtable-linkage.cpp @@ -128,10 +128,8 @@ void use_F(F<char> &fc) { // CHECK: @_ZTI1FIlE = weak_odr constant // F<int> is an explicit template instantiation declaration without a -// key function, so its vtable should have weak_odr linkage. -// CHECK: @_ZTV1FIiE = weak_odr constant -// CHECK: @_ZTS1FIiE = weak_odr constant -// CHECK: @_ZTI1FIiE = weak_odr constant +// key function, so its vtable should have external linkage. +// CHECK: @_ZTV1FIiE = external constant // E<int> is an explicit template instantiation declaration. It has a // key function that is not instantiated, so we should only reference diff --git a/test/Parser/check-syntax-1.m b/test/Parser/check-syntax-1.m index a1999de..085ff4c 100644 --- a/test/Parser/check-syntax-1.m +++ b/test/Parser/check-syntax-1.m @@ -9,3 +9,13 @@ typedef float CGFloat; // expected-error {{ expected ';' after method prototype}} @end +// rdar: // 7822196 +@interface A +(void) x; // expected-error {{method type specifier must start with '-' or '+'}} \ + // expected-warning {{type specifier missing, defaults to 'int' [-Wimplicit-int]}} \ + // expected-error {{cannot declare variable inside @interface or @protocol}} +(int)im; // expected-error {{method type specifier must start with '-' or '+'}} \ +- ok; +@end + + diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp index e2a966bd..49bcd99 100644 --- a/test/SemaCXX/conditional-expr.cpp +++ b/test/SemaCXX/conditional-expr.cpp @@ -213,3 +213,30 @@ namespace PR6595 { (void)(Cond? a : S); } } + +namespace PR6757 { + struct Foo1 { + Foo1(); + Foo1(const Foo1&); + }; + + struct Foo2 { }; + + struct Foo3 { + Foo3(); + Foo3(Foo3&); + }; + + struct Bar { + operator const Foo1&() const; + operator const Foo2&() const; + operator const Foo3&() const; + }; + + void f() { + (void)(true ? Bar() : Foo1()); // okay + (void)(true ? Bar() : Foo2()); // okay + // FIXME: Diagnostic below could be improved + (void)(true ? Bar() : Foo3()); // expected-error{{incompatible operand types ('PR6757::Bar' and 'PR6757::Foo3')}} + } +} diff --git a/test/SemaCXX/copy-initialization.cpp b/test/SemaCXX/copy-initialization.cpp index 3a63be0..e5b1fd7 100644 --- a/test/SemaCXX/copy-initialization.cpp +++ b/test/SemaCXX/copy-initialization.cpp @@ -21,3 +21,23 @@ struct foo { // PR3600 void test(const foo *P) { P->bar(); } // expected-error{{cannot initialize object parameter of type 'foo' with an expression of type 'foo const'}} + +namespace PR6757 { + struct Foo { + Foo(); + Foo(Foo&); + }; + + struct Bar { + operator const Foo&() const; + }; + + void f(Foo); // expected-note{{candidate function not viable: no known conversion from 'PR6757::Bar' to 'PR6757::Foo' for 1st argument}} + + // FIXME: This isn't really the right reason for the failure. We + // should fail after overload resolution. + void g(Foo foo) { + f(Bar()); // expected-error{{no matching function for call to 'f'}} + f(foo); + } +} diff --git a/test/SemaObjC/class-extension-after-implementation.m b/test/SemaObjC/class-extension-after-implementation.m new file mode 100644 index 0000000..2d8a5b1 --- /dev/null +++ b/test/SemaObjC/class-extension-after-implementation.m @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// rdar://7822210 + +@interface A @end + +@implementation A @end // expected-note {{class implementation is declared here}} + +@interface A () // expected-error {{cannot declare class extension for 'A' after class implementation}} +-(void) im0; +@end + diff --git a/test/SemaObjC/default-synthesize.m b/test/SemaObjC/default-synthesize.m index be2397b..45a3710 100644 --- a/test/SemaObjC/default-synthesize.m +++ b/test/SemaObjC/default-synthesize.m @@ -23,12 +23,12 @@ //@synthesize howMany, what; - (int) howMany { - return howMany; + return self.howMany; } // - (void) setHowMany: (int) value - (NSString*) what { - return what; + return self.what; } // - (void) setWhat: (NSString*) value @end @@ -44,12 +44,12 @@ // - (int) howMany - (void) setHowMany: (int) value { - howMany = value; + self.howMany = value; } // - (NSString*) what - (void) setWhat: (NSString*) value { - if (what != value) { + if (self.what != value) { } } @end @@ -64,17 +64,17 @@ //@synthesize howMany, what; // REM: Redundant anyway - (int) howMany { - return howMany; + return self.howMany; } - (void) setHowMany: (int) value { - howMany = value; + self.howMany = value; } - (NSString*) what { - return what; + return self.what; } - (void) setWhat: (NSString*) value { - if (what != value) { + if (self.what != value) { } } @end |