diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 786393cc31..975659b1e5 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -688,22 +688,40 @@ public: /// no base classes, and no virtual functions (C++ [dcl.init.aggr]p1). bool isAggregate() const { return data().Aggregate; } + /// setAggregate - Set whether this class is an aggregate (C++ + /// [dcl.init.aggr]). + void setAggregate(bool Agg) { data().Aggregate = Agg; } + + /// setMethodAsVirtual - Make input method virtual and set the necesssary + /// special function bits and other bits accordingly. + void setMethodAsVirtual(FunctionDecl *Method); + /// isPOD - Whether this class is a POD-type (C++ [class]p4), which is a class /// that is an aggregate that has no non-static non-POD data members, no /// reference data members, no user-defined copy assignment operator and no /// user-defined destructor. bool isPOD() const { return data().PlainOldData; } + /// setPOD - Set whether this class is a POD-type (C++ [class]p4). + void setPOD(bool POD) { data().PlainOldData = POD; } + /// isEmpty - Whether this class is empty (C++0x [meta.unary.prop]), which /// means it has a virtual function, virtual base, data member (other than /// 0-width bit-field) or inherits from a non-empty class. Does NOT include /// a check for union-ness. bool isEmpty() const { return data().Empty; } + /// Set whether this class is empty (C++0x [meta.unary.prop]) + void setEmpty(bool Emp) { data().Empty = Emp; } + /// isPolymorphic - Whether this class is polymorphic (C++ [class.virtual]), /// which means that the class contains or inherits a virtual function. bool isPolymorphic() const { return data().Polymorphic; } + /// setPolymorphic - Set whether this class is polymorphic (C++ + /// [class.virtual]). + void setPolymorphic(bool Poly) { data().Polymorphic = Poly; } + /// isAbstract - Whether this class is abstract (C++ [class.abstract]), /// which means that the class contains or inherits a pure virtual function. bool isAbstract() const { return data().Abstract; } @@ -715,22 +733,42 @@ public: // (C++ [class.ctor]p5) bool hasTrivialConstructor() const { return data().HasTrivialConstructor; } + // setHasTrivialConstructor - Set whether this class has a trivial constructor + // (C++ [class.ctor]p5) + void setHasTrivialConstructor(bool TC) { data().HasTrivialConstructor = TC; } + // hasTrivialCopyConstructor - Whether this class has a trivial copy // constructor (C++ [class.copy]p6) bool hasTrivialCopyConstructor() const { return data().HasTrivialCopyConstructor; } + // setHasTrivialCopyConstructor - Set whether this class has a trivial + // copy constructor (C++ [class.copy]p6) + void setHasTrivialCopyConstructor(bool TC) { + data().HasTrivialCopyConstructor = TC; + } + // hasTrivialCopyAssignment - Whether this class has a trivial copy // assignment operator (C++ [class.copy]p11) bool hasTrivialCopyAssignment() const { return data().HasTrivialCopyAssignment; } + // setHasTrivialCopyAssignment - Set whether this class has a + // trivial copy assignment operator (C++ [class.copy]p11) + void setHasTrivialCopyAssignment(bool TC) { + data().HasTrivialCopyAssignment = TC; + } + // hasTrivialDestructor - Whether this class has a trivial destructor // (C++ [class.dtor]p3) bool hasTrivialDestructor() const { return data().HasTrivialDestructor; } + // setHasTrivialDestructor - Set whether this class has a trivial destructor + // (C++ [class.dtor]p3) + void setHasTrivialDestructor(bool TC) { data().HasTrivialDestructor = TC; } + /// \brief If this record is an instantiation of a member class, /// retrieves the member class from which it was instantiated. /// diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 5445c1b755..5d8ead37dc 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -2584,6 +2584,13 @@ public: bool Virtual, AccessSpecifier Access, TypeSourceInfo *TInfo); + /// SetClassDeclAttributesFromBase - Copies class decl traits + /// (such as whether the class has a trivial constructor, + /// trivial destructor etc) from the given base class. + void SetClassDeclAttributesFromBase(CXXRecordDecl *Class, + const CXXRecordDecl *BaseClass, + bool BaseIsVirtual); + BaseResult ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, bool Virtual, AccessSpecifier Access, diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 57780ef981..fdeac1ebf8 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -3138,6 +3138,10 @@ QualType ASTContext::getObjCFastEnumerationStateType() { Field->setAccess(AS_public); ObjCFastEnumerationStateTypeDecl->addDecl(Field); } + if (getLangOptions().CPlusPlus) + if (CXXRecordDecl *CXXRD = + dyn_cast(ObjCFastEnumerationStateTypeDecl)) + CXXRD->setEmpty(false); ObjCFastEnumerationStateTypeDecl->completeDefinition(); } diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 3e6d8b379f..5d9a09da70 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -97,25 +97,6 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, CXXRecordDecl *BaseClassDecl = cast(BaseType->getAs()->getDecl()); - // C++ [dcl.init.aggr]p1: - // An aggregate is [...] a class with [...] no base classes [...]. - data().Aggregate = false; - - // C++ [class]p4: - // A POD-struct is an aggregate class... - data().PlainOldData = false; - - // A class with a non-empty base class is not empty. - // FIXME: Standard ref? - if (!BaseClassDecl->isEmpty()) - data().Empty = false; - - // C++ [class.virtual]p1: - // A class that declares or inherits a virtual function is called a - // polymorphic class. - if (BaseClassDecl->isPolymorphic()) - data().Polymorphic = true; - // Now go through all virtual bases of this base and add them. for (CXXRecordDecl::base_class_iterator VBase = BaseClassDecl->vbases_begin(), @@ -129,50 +110,8 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // Add this base if it's not already in the list. if (SeenVBaseTypes.insert(C.getCanonicalType(BaseType))) VBases.push_back(Base); - - // C++0x [meta.unary.prop] is_empty: - // T is a class type, but not a union type, with ... no virtual base - // classes - data().Empty = false; - - // C++ [class.ctor]p5: - // A constructor is trivial if its class has no virtual base classes. - data().HasTrivialConstructor = false; - - // C++ [class.copy]p6: - // A copy constructor is trivial if its class has no virtual base - // classes. - data().HasTrivialCopyConstructor = false; - - // C++ [class.copy]p11: - // A copy assignment operator is trivial if its class has no virtual - // base classes. - data().HasTrivialCopyAssignment = false; - } else { - // C++ [class.ctor]p5: - // A constructor is trivial if all the direct base classes of its - // class have trivial constructors. - if (!BaseClassDecl->hasTrivialConstructor()) - data().HasTrivialConstructor = false; - - // C++ [class.copy]p6: - // A copy constructor is trivial if all the direct base classes of its - // class have trivial copy constructors. - if (!BaseClassDecl->hasTrivialCopyConstructor()) - data().HasTrivialCopyConstructor = false; - - // C++ [class.copy]p11: - // A copy assignment operator is trivial if all the direct base classes - // of its class have trivial copy assignment operators. - if (!BaseClassDecl->hasTrivialCopyAssignment()) - data().HasTrivialCopyAssignment = false; } - - // C++ [class.ctor]p3: - // A destructor is trivial if all the direct base classes of its class - // have trivial destructors. - if (!BaseClassDecl->hasTrivialDestructor()) - data().HasTrivialDestructor = false; + } if (VBases.empty()) @@ -329,33 +268,6 @@ CXXRecordDecl::addedMember(Decl *D) { if (FunTmpl) D = FunTmpl->getTemplatedDecl(); - if (CXXMethodDecl *Method = dyn_cast(D)) { - if (Method->isVirtual()) { - // C++ [dcl.init.aggr]p1: - // An aggregate is an array or a class with [...] no virtual functions. - data().Aggregate = false; - - // C++ [class]p4: - // A POD-struct is an aggregate class... - data().PlainOldData = false; - - // Virtual functions make the class non-empty. - // FIXME: Standard ref? - data().Empty = false; - - // C++ [class.virtual]p1: - // A class that declares or inherits a virtual function is called a - // polymorphic class. - data().Polymorphic = true; - - // None of the special member functions are trivial. - data().HasTrivialConstructor = false; - data().HasTrivialCopyConstructor = false; - data().HasTrivialCopyAssignment = false; - // FIXME: Destructor? - } - } - if (D->isImplicit()) { if (CXXConstructorDecl *Constructor = dyn_cast(D)) { // If this is the implicit default constructor, note that we have now @@ -422,19 +334,6 @@ CXXRecordDecl::addedMember(Decl *D) { if (isa(D)) { data().DeclaredDestructor = true; data().UserDeclaredDestructor = true; - - // C++ [class]p4: - // A POD-struct is an aggregate class that has [...] no user-defined - // destructor. - data().PlainOldData = false; - - // C++ [class.dtor]p3: - // A destructor is trivial if it is an implicitly-declared destructor and - // [...]. - // - // FIXME: C++0x: don't do this for "= default" destructors - data().HasTrivialDestructor = false; - return; } @@ -483,57 +382,6 @@ CXXRecordDecl::addedMember(Decl *D) { return; } - - // Handle non-static data members. - if (FieldDecl *Field = dyn_cast(D)) { - // C++ [dcl.init.aggr]p1: - // An aggregate is an array or a class (clause 9) with [...] no - // private or protected non-static data members (clause 11). - // - // A POD must be an aggregate. - if (D->getAccess() == AS_private || D->getAccess() == AS_protected) { - data().Aggregate = false; - data().PlainOldData = false; - } - - // C++ [class]p9: - // A POD struct is a class that is both a trivial class and a - // standard-layout class, and has no non-static data members of type - // non-POD struct, non-POD union (or array of such types). - ASTContext &Context = getASTContext(); - QualType T = Context.getBaseElementType(Field->getType()); - if (!T->isPODType()) - data().PlainOldData = false; - if (T->isReferenceType()) - data().HasTrivialConstructor = false; - - if (const RecordType *RecordTy = T->getAs()) { - CXXRecordDecl* FieldRec = cast(RecordTy->getDecl()); - if (FieldRec->getDefinition()) { - if (!FieldRec->hasTrivialConstructor()) - data().HasTrivialConstructor = false; - if (!FieldRec->hasTrivialCopyConstructor()) - data().HasTrivialCopyConstructor = false; - if (!FieldRec->hasTrivialCopyAssignment()) - data().HasTrivialCopyAssignment = false; - if (!FieldRec->hasTrivialDestructor()) - data().HasTrivialDestructor = false; - } - } - - // If this is not a zero-length bit-field, then the class is not empty. - if (data().Empty) { - if (!Field->getBitWidth()) - data().Empty = false; - else if (!Field->getBitWidth()->isTypeDependent() && - !Field->getBitWidth()->isValueDependent()) { - llvm::APSInt Bits; - if (Field->getBitWidth()->isIntegerConstantExpr(Bits, Context)) - if (!!Bits) - data().Empty = false; - } - } - } } static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) { @@ -716,6 +564,17 @@ void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) { llvm_unreachable("conversion not found in set!"); } +void CXXRecordDecl::setMethodAsVirtual(FunctionDecl *Method) { + Method->setVirtualAsWritten(true); + setAggregate(false); + setPOD(false); + setEmpty(false); + setPolymorphic(true); + setHasTrivialConstructor(false); + setHasTrivialCopyConstructor(false); + setHasTrivialCopyAssignment(false); +} + CXXRecordDecl *CXXRecordDecl::getInstantiatedFromMemberClass() const { if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) return cast(MSInfo->getInstantiatedFrom()); diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 443b7c089f..1dd9b4365b 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -1869,6 +1869,33 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, } } +llvm::Value * +CodeGenFunction::BuildVector(const llvm::SmallVectorImpl &Ops) { + assert((Ops.size() & (Ops.size() - 1)) == 0 && + "Not a power-of-two sized vector!"); + bool AllConstants = true; + for (unsigned I = 0, E = Ops.size(); I != E && AllConstants; ++I) + AllConstants &= isa(Ops[I]); + + // If this is a constant vector, create a ConstantVector. + if (AllConstants) { + std::vector CstOps; + for (unsigned I = 0, E = Ops.size(); I != E; ++I) + CstOps.push_back(cast(Ops[I])); + return ConstantVector::get(CstOps); + } + + // Otherwise, insertelement the values to build the vector. + Value *Result = + llvm::UndefValue::get(llvm::VectorType::get(Ops[0]->getType(), Ops.size())); + + for (unsigned I = 0, E = Ops.size(); I != E; ++I) + Result = Builder.CreateInsertElement(Result, Ops[I], + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), I)); + + return Result; +} + Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E) { @@ -1986,6 +2013,11 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, llvm::Function *F = CGM.getIntrinsic(ID); return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), name); } + case X86::BI__builtin_ia32_vec_init_v8qi: + case X86::BI__builtin_ia32_vec_init_v4hi: + case X86::BI__builtin_ia32_vec_init_v2si: + return Builder.CreateBitCast(BuildVector(Ops), + llvm::Type::getX86_MMXTy(VMContext)); case X86::BI__builtin_ia32_cmpps: { llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_sse_cmp_ps); return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), "cmpps"); @@ -2035,37 +2067,6 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, Ops[0] = Builder.CreateBitCast(Ops[0], PtrTy); return Builder.CreateStore(Ops[1], Ops[0]); } - case X86::BI__builtin_ia32_palignr: { - unsigned shiftVal = cast(Ops[2])->getZExtValue(); - - // If palignr is shifting the pair of input vectors less than 9 bytes, - // emit a shuffle instruction. - if (shiftVal <= 8) { - llvm::SmallVector Indices; - for (unsigned i = 0; i != 8; ++i) - Indices.push_back(llvm::ConstantInt::get(Int32Ty, shiftVal + i)); - - Value* SV = llvm::ConstantVector::get(Indices.begin(), Indices.size()); - return Builder.CreateShuffleVector(Ops[1], Ops[0], SV, "palignr"); - } - - // If palignr is shifting the pair of input vectors more than 8 but less - // than 16 bytes, emit a logical right shift of the destination. - if (shiftVal < 16) { - // MMX has these as 1 x i64 vectors for some odd optimization reasons. - const llvm::Type *VecTy = llvm::VectorType::get(Int64Ty, 1); - - Ops[0] = Builder.CreateBitCast(Ops[0], VecTy, "cast"); - Ops[1] = llvm::ConstantInt::get(VecTy, (shiftVal-8) * 8); - - // create i32 constant - llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_mmx_psrl_q); - return Builder.CreateCall(F, &Ops[0], &Ops[0] + 2, "palignr"); - } - - // If palignr is shifting the pair of vectors more than 32 bytes, emit zero. - return llvm::Constant::getNullValue(ConvertType(E->getType())); - } case X86::BI__builtin_ia32_palignr128: { unsigned shiftVal = cast(Ops[2])->getZExtValue(); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 8dc8ac1e3d..8298443b6c 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -536,6 +536,9 @@ public: llvm::BasicBlock *getInvokeDestImpl(); + // Build a vector out of the supplied Values. + llvm::Value *BuildVector(const llvm::SmallVectorImpl &Ops); + public: /// ObjCEHValueStack - Stack of Objective-C exception values, used for /// rethrows. diff --git a/lib/Headers/mmintrin.h b/lib/Headers/mmintrin.h index bad9e1c059..fefb42fd74 100644 --- a/lib/Headers/mmintrin.h +++ b/lib/Headers/mmintrin.h @@ -43,14 +43,13 @@ _mm_empty(void) static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_cvtsi32_si64(int __i) { - return (__m64)(__v2si){__i, 0}; + return (__m64)__builtin_ia32_vec_init_v2si(__i, 0); } static __inline__ int __attribute__((__always_inline__, __nodebug__)) _mm_cvtsi64_si32(__m64 __m) { - __v2si __mmx_var2 = (__v2si)__m; - return __mmx_var2[0]; + return __builtin_ia32_vec_ext_v2si((__v2si)__m, 0); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) @@ -86,59 +85,55 @@ _mm_packs_pu16(__m64 __m1, __m64 __m2) static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_unpackhi_pi8(__m64 __m1, __m64 __m2) { - return (__m64)__builtin_shufflevector((__v8qi)__m1, (__v8qi)__m2, 4, 8+4, 5, - 8+5, 6, 8+6, 7, 8+7); + return (__m64)__builtin_ia32_punpckhbw((__v8qi)__m1, (__v8qi)__m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_unpackhi_pi16(__m64 __m1, __m64 __m2) { - return (__m64)__builtin_shufflevector((__v4hi)__m1, (__v4hi)__m2, 2, 4+2, 3, - 4+3); + return (__m64)__builtin_ia32_punpckhwd((__v4hi)__m1, (__v4hi)__m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_unpackhi_pi32(__m64 __m1, __m64 __m2) { - return (__m64)__builtin_shufflevector((__v2si)__m1, (__v2si)__m2, 1, 2+1); + return (__m64)__builtin_ia32_punpckhdq((__v2si)__m1, (__v2si)__m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_unpacklo_pi8(__m64 __m1, __m64 __m2) { - return (__m64)__builtin_shufflevector((__v8qi)__m1, (__v8qi)__m2, 0, 8+0, 1, - 8+1, 2, 8+2, 3, 8+3); + return (__m64)__builtin_ia32_punpcklbw((__v8qi)__m1, (__v8qi)__m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_unpacklo_pi16(__m64 __m1, __m64 __m2) { - return (__m64)__builtin_shufflevector((__v4hi)__m1, (__v4hi)__m2, 0, 4+0, 1, - 4+1); + return (__m64)__builtin_ia32_punpcklwd((__v4hi)__m1, (__v4hi)__m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_unpacklo_pi32(__m64 __m1, __m64 __m2) { - return (__m64)__builtin_shufflevector((__v2si)__m1, (__v2si)__m2, 0, 2+0); + return (__m64)__builtin_ia32_punpckldq((__v2si)__m1, (__v2si)__m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_add_pi8(__m64 __m1, __m64 __m2) { - return (__m64)((__v8qi)__m1 + (__v8qi)__m2); + return (__m64)__builtin_ia32_paddb((__v8qi)__m1, (__v8qi)__m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_add_pi16(__m64 __m1, __m64 __m2) { - return (__m64)((__v4hi)__m1 + (__v4hi)__m2); + return (__m64)__builtin_ia32_paddw((__v4hi)__m1, (__v4hi)__m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_add_pi32(__m64 __m1, __m64 __m2) { - return (__m64)((__v2si)__m1 + (__v2si)__m2); + return (__m64)__builtin_ia32_paddd((__v2si)__m1, (__v2si)__m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) @@ -168,19 +163,19 @@ _mm_adds_pu16(__m64 __m1, __m64 __m2) static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_sub_pi8(__m64 __m1, __m64 __m2) { - return (__m64)((__v8qi)__m1 - (__v8qi)__m2); + return (__m64)__builtin_ia32_psubb((__v8qi)__m1, (__v8qi)__m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_sub_pi16(__m64 __m1, __m64 __m2) { - return (__m64)((__v4hi)__m1 - (__v4hi)__m2); + return (__m64)__builtin_ia32_psubw((__v4hi)__m1, (__v4hi)__m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_sub_pi32(__m64 __m1, __m64 __m2) { - return (__m64)((__v2si)__m1 - (__v2si)__m2); + return (__m64)__builtin_ia32_psubd((__v2si)__m1, (__v2si)__m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) @@ -222,7 +217,7 @@ _mm_mulhi_pi16(__m64 __m1, __m64 __m2) static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_mullo_pi16(__m64 __m1, __m64 __m2) { - return (__m64)((__v4hi)__m1 * (__v4hi)__m2); + return (__m64)__builtin_ia32_pmullw((__v4hi)__m1, (__v4hi)__m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) @@ -252,13 +247,13 @@ _mm_slli_pi32(__m64 __m, int __count) static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_sll_si64(__m64 __m, __m64 __count) { - return __builtin_ia32_psllq(__m, __count); + return (__m64)__builtin_ia32_psllq(__m, __count); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_slli_si64(__m64 __m, int __count) { - return __builtin_ia32_psllqi(__m, __count); + return (__m64)__builtin_ia32_psllqi(__m, __count); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) @@ -318,67 +313,67 @@ _mm_srl_si64(__m64 __m, __m64 __count) static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_srli_si64(__m64 __m, int __count) { - return __builtin_ia32_psrlqi(__m, __count); + return (__m64)__builtin_ia32_psrlqi(__m, __count); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_and_si64(__m64 __m1, __m64 __m2) { - return __m1 & __m2; + return __builtin_ia32_pand(__m1, __m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_andnot_si64(__m64 __m1, __m64 __m2) { - return ~__m1 & __m2; + return __builtin_ia32_pandn(__m1, __m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_or_si64(__m64 __m1, __m64 __m2) { - return __m1 | __m2; + return __builtin_ia32_por(__m1, __m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_xor_si64(__m64 __m1, __m64 __m2) { - return __m1 ^ __m2; + return __builtin_ia32_pxor(__m1, __m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_cmpeq_pi8(__m64 __m1, __m64 __m2) { - return (__m64)((__v8qi)__m1 == (__v8qi)__m2); + return (__m64)__builtin_ia32_pcmpeqb((__v8qi)__m1, (__v8qi)__m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_cmpeq_pi16(__m64 __m1, __m64 __m2) { - return (__m64)((__v4hi)__m1 == (__v4hi)__m2); + return (__m64)__builtin_ia32_pcmpeqw((__v4hi)__m1, (__v4hi)__m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_cmpeq_pi32(__m64 __m1, __m64 __m2) { - return (__m64)((__v2si)__m1 == (__v2si)__m2); + return (__m64)__builtin_ia32_pcmpeqd((__v2si)__m1, (__v2si)__m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_cmpgt_pi8(__m64 __m1, __m64 __m2) { - return (__m64)((__v8qi)__m1 > (__v8qi)__m2); + return (__m64)__builtin_ia32_pcmpgtb((__v8qi)__m1, (__v8qi)__m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_cmpgt_pi16(__m64 __m1, __m64 __m2) { - return (__m64)((__v4hi)__m1 > (__v4hi)__m2); + return (__m64)__builtin_ia32_pcmpgtw((__v4hi)__m1, (__v4hi)__m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_cmpgt_pi32(__m64 __m1, __m64 __m2) { - return (__m64)((__v2si)__m1 > (__v2si)__m2); + return (__m64)__builtin_ia32_pcmpgtd((__v2si)__m1, (__v2si)__m2); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) @@ -390,57 +385,58 @@ _mm_setzero_si64(void) static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_set_pi32(int __i1, int __i0) { - return (__m64)(__v2si){ __i0, __i1 }; + return (__m64)__builtin_ia32_vec_init_v2si(__i0, __i1); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_set_pi16(short __s3, short __s2, short __s1, short __s0) { - return (__m64)(__v4hi){ __s0, __s1, __s2, __s3 }; + return (__m64)__builtin_ia32_vec_init_v4hi(__s0, __s1, __s2, __s3); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_set_pi8(char __b7, char __b6, char __b5, char __b4, char __b3, char __b2, char __b1, char __b0) { - return (__m64)(__v8qi){ __b0, __b1, __b2, __b3, __b4, __b5, __b6, __b7 }; + return (__m64)__builtin_ia32_vec_init_v8qi(__b0, __b1, __b2, __b3, + __b4, __b5, __b6, __b7); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_set1_pi32(int __i) { - return (__m64)(__v2si){ __i, __i }; + return _mm_set_pi32(__i, __i); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) -_mm_set1_pi16(short __s) +_mm_set1_pi16(short __w) { - return (__m64)(__v4hi){ __s, __s, __s, __s }; + return _mm_set_pi16(__w, __w, __w, __w); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_set1_pi8(char __b) { - return (__m64)(__v8qi){ __b, __b, __b, __b, __b, __b, __b, __b }; + return _mm_set_pi8(__b, __b, __b, __b, __b, __b, __b, __b); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_setr_pi32(int __i1, int __i0) { - return (__m64)(__v2si){ __i1, __i0 }; + return _mm_set_pi32(__i1, __i0); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) -_mm_setr_pi16(short __s3, short __s2, short __s1, short __s0) +_mm_setr_pi16(short __w3, short __w2, short __w1, short __w0) { - return (__m64)(__v4hi){ __s3, __s2, __s1, __s0 }; + return _mm_set_pi16(__w3, __w2, __w1, __w0); } static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) _mm_setr_pi8(char __b7, char __b6, char __b5, char __b4, char __b3, char __b2, char __b1, char __b0) { - return (__m64)(__v8qi){ __b7, __b6, __b5, __b4, __b3, __b2, __b1, __b0 }; + return _mm_set_pi8(__b7, __b6, __b5, __b4, __b3, __b2, __b1, __b0); } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index c189bce8eb..68cdc556e8 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1958,8 +1958,11 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, TInfo, /*BitWidth=*/0, /*Mutable=*/false); Anon->setAccess(AS); - if (getLangOptions().CPlusPlus) + if (getLangOptions().CPlusPlus) { FieldCollector->Add(cast(Anon)); + if (!cast(Record)->isEmpty()) + cast(OwningClass)->setEmpty(false); + } } else { DeclSpec::SCS SCSpec = DS.getStorageClassSpec(); assert(SCSpec != DeclSpec::SCS_typedef && @@ -3425,7 +3428,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, << FixItHint::CreateRemoval(D.getDeclSpec().getVirtualSpecLoc()); } else { // Okay: Add virtual to the method. - NewFD->setVirtualAsWritten(true); + CXXRecordDecl *CurClass = cast(DC); + CurClass->setMethodAsVirtual(NewFD); } } @@ -3926,6 +3930,15 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, return NewFD->setInvalidDecl(); } } + + // C++ [class]p4: A POD-struct is an aggregate class that has [...] no + // user-defined destructor. + Record->setPOD(false); + + // C++ [class.dtor]p3: A destructor is trivial if it is an implicitly- + // declared destructor. + // FIXME: C++0x: don't do this for "= default" destructors + Record->setHasTrivialDestructor(false); } else if (CXXConversionDecl *Conversion = dyn_cast(NewFD)) { ActOnConversionDeclarator(Conversion); @@ -6179,9 +6192,27 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, } if (!InvalidDecl && getLangOptions().CPlusPlus) { + CXXRecordDecl* CXXRecord = cast(Record); + + if (!T->isPODType()) + CXXRecord->setPOD(false); + if (!ZeroWidth) + CXXRecord->setEmpty(false); + if (T->isReferenceType()) + CXXRecord->setHasTrivialConstructor(false); + if (const RecordType *RT = EltTy->getAs()) { CXXRecordDecl* RDecl = cast(RT->getDecl()); if (RDecl->getDefinition()) { + if (!RDecl->hasTrivialConstructor()) + CXXRecord->setHasTrivialConstructor(false); + if (!RDecl->hasTrivialCopyConstructor()) + CXXRecord->setHasTrivialCopyConstructor(false); + if (!RDecl->hasTrivialCopyAssignment()) + CXXRecord->setHasTrivialCopyAssignment(false); + if (!RDecl->hasTrivialDestructor()) + CXXRecord->setHasTrivialDestructor(false); + // C++ 9.5p1: An object of a class with a non-trivial // constructor, a non-trivial copy constructor, a non-trivial // destructor, or a non-trivial copy assignment operator @@ -6204,6 +6235,18 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, Diag(Loc, diag::warn_attribute_weak_on_field); NewFD->setAccess(AS); + + // C++ [dcl.init.aggr]p1: + // An aggregate is an array or a class (clause 9) with [...] no + // private or protected non-static data members (clause 11). + // A POD must be an aggregate. + if (getLangOptions().CPlusPlus && + (AS == AS_private || AS == AS_protected)) { + CXXRecordDecl *CXXRecord = cast(Record); + CXXRecord->setAggregate(false); + CXXRecord->setPOD(false); + } + return NewFD; } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 63acb095a6..473247139e 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -502,6 +502,8 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, return 0; } + SetClassDeclAttributesFromBase(Class, CXXBaseDecl, Virtual); + if (BaseDecl->isInvalidDecl()) Class->setInvalidDecl(); @@ -511,6 +513,73 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, Access, TInfo); } +void Sema::SetClassDeclAttributesFromBase(CXXRecordDecl *Class, + const CXXRecordDecl *BaseClass, + bool BaseIsVirtual) { + // A class with a non-empty base class is not empty. + // FIXME: Standard ref? + if (!BaseClass->isEmpty()) + Class->setEmpty(false); + + // C++ [class.virtual]p1: + // A class that [...] inherits a virtual function is called a polymorphic + // class. + if (BaseClass->isPolymorphic()) + Class->setPolymorphic(true); + + // C++ [dcl.init.aggr]p1: + // An aggregate is [...] a class with [...] no base classes [...]. + Class->setAggregate(false); + + // C++ [class]p4: + // A POD-struct is an aggregate class... + Class->setPOD(false); + + if (BaseIsVirtual) { + // C++ [class.ctor]p5: + // A constructor is trivial if its class has no virtual base classes. + Class->setHasTrivialConstructor(false); + + // C++ [class.copy]p6: + // A copy constructor is trivial if its class has no virtual base classes. + Class->setHasTrivialCopyConstructor(false); + + // C++ [class.copy]p11: + // A copy assignment operator is trivial if its class has no virtual + // base classes. + Class->setHasTrivialCopyAssignment(false); + + // C++0x [meta.unary.prop] is_empty: + // T is a class type, but not a union type, with ... no virtual base + // classes + Class->setEmpty(false); + } else { + // C++ [class.ctor]p5: + // A constructor is trivial if all the direct base classes of its + // class have trivial constructors. + if (!BaseClass->hasTrivialConstructor()) + Class->setHasTrivialConstructor(false); + + // C++ [class.copy]p6: + // A copy constructor is trivial if all the direct base classes of its + // class have trivial copy constructors. + if (!BaseClass->hasTrivialCopyConstructor()) + Class->setHasTrivialCopyConstructor(false); + + // C++ [class.copy]p11: + // A copy assignment operator is trivial if all the direct base classes + // of its class have trivial copy assignment operators. + if (!BaseClass->hasTrivialCopyAssignment()) + Class->setHasTrivialCopyAssignment(false); + } + + // C++ [class.ctor]p3: + // A destructor is trivial if all the direct base classes of its class + // have trivial destructors. + if (!BaseClass->hasTrivialDestructor()) + Class->setHasTrivialDestructor(false); +} + /// ActOnBaseSpecifier - Parsed a base specifier. A base specifier is /// one entry in the base class list of a class specifier, for /// example: diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index a2c3df653b..5520f64044 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -1091,6 +1091,13 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation, Base = Pattern->bases_begin(), BaseEnd = Pattern->bases_end(); Base != BaseEnd; ++Base) { if (!Base->getType()->isDependentType()) { + const CXXRecordDecl *BaseDecl = + cast(Base->getType()->getAs()->getDecl()); + + // Make sure to set the attributes from the base. + SetClassDeclAttributesFromBase(Instantiation, BaseDecl, + Base->isVirtual()); + InstantiatedBases.push_back(new (Context) CXXBaseSpecifier(*Base)); continue; } diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index d87629151e..f9ff20463a 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1996,9 +1996,10 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New, if (InitFunctionInstantiation(New, Tmpl)) return true; + CXXRecordDecl *Record = cast(Owner); New->setAccess(Tmpl->getAccess()); if (Tmpl->isVirtualAsWritten()) - New->setVirtualAsWritten(true); + Record->setMethodAsVirtual(New); // FIXME: attributes // FIXME: New needs a pointer to Tmpl