/// 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; }
// (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.
///
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,
Field->setAccess(AS_public);
ObjCFastEnumerationStateTypeDecl->addDecl(Field);
}
+ if (getLangOptions().CPlusPlus)
+ if (CXXRecordDecl *CXXRD =
+ dyn_cast<CXXRecordDecl>(ObjCFastEnumerationStateTypeDecl))
+ CXXRD->setEmpty(false);
ObjCFastEnumerationStateTypeDecl->completeDefinition();
}
CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->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(),
// 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())
if (FunTmpl)
D = FunTmpl->getTemplatedDecl();
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(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<CXXConstructorDecl>(D)) {
// If this is the implicit default constructor, note that we have now
if (isa<CXXDestructorDecl>(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;
}
return;
}
-
- // Handle non-static data members.
- if (FieldDecl *Field = dyn_cast<FieldDecl>(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<RecordType>()) {
- CXXRecordDecl* FieldRec = cast<CXXRecordDecl>(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) {
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<CXXRecordDecl>(MSInfo->getInstantiatedFrom());
}
}
+llvm::Value *
+CodeGenFunction::BuildVector(const llvm::SmallVectorImpl<llvm::Value*> &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<Constant>(Ops[I]);
+
+ // If this is a constant vector, create a ConstantVector.
+ if (AllConstants) {
+ std::vector<Constant*> CstOps;
+ for (unsigned I = 0, E = Ops.size(); I != E; ++I)
+ CstOps.push_back(cast<Constant>(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) {
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");
Ops[0] = Builder.CreateBitCast(Ops[0], PtrTy);
return Builder.CreateStore(Ops[1], Ops[0]);
}
- case X86::BI__builtin_ia32_palignr: {
- unsigned shiftVal = cast<llvm::ConstantInt>(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<llvm::Constant*, 8> 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<llvm::ConstantInt>(Ops[2])->getZExtValue();
llvm::BasicBlock *getInvokeDestImpl();
+ // Build a vector out of the supplied Values.
+ llvm::Value *BuildVector(const llvm::SmallVectorImpl<llvm::Value*> &Ops);
+
public:
/// ObjCEHValueStack - Stack of Objective-C exception values, used for
/// rethrows.
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__))
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__))
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__))
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__))
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__))
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__))
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);
}
TInfo,
/*BitWidth=*/0, /*Mutable=*/false);
Anon->setAccess(AS);
- if (getLangOptions().CPlusPlus)
+ if (getLangOptions().CPlusPlus) {
FieldCollector->Add(cast<FieldDecl>(Anon));
+ if (!cast<CXXRecordDecl>(Record)->isEmpty())
+ cast<CXXRecordDecl>(OwningClass)->setEmpty(false);
+ }
} else {
DeclSpec::SCS SCSpec = DS.getStorageClassSpec();
assert(SCSpec != DeclSpec::SCS_typedef &&
<< FixItHint::CreateRemoval(D.getDeclSpec().getVirtualSpecLoc());
} else {
// Okay: Add virtual to the method.
- NewFD->setVirtualAsWritten(true);
+ CXXRecordDecl *CurClass = cast<CXXRecordDecl>(DC);
+ CurClass->setMethodAsVirtual(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<CXXConversionDecl>(NewFD)) {
ActOnConversionDeclarator(Conversion);
}
if (!InvalidDecl && getLangOptions().CPlusPlus) {
+ CXXRecordDecl* CXXRecord = cast<CXXRecordDecl>(Record);
+
+ if (!T->isPODType())
+ CXXRecord->setPOD(false);
+ if (!ZeroWidth)
+ CXXRecord->setEmpty(false);
+ if (T->isReferenceType())
+ CXXRecord->setHasTrivialConstructor(false);
+
if (const RecordType *RT = EltTy->getAs<RecordType>()) {
CXXRecordDecl* RDecl = cast<CXXRecordDecl>(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
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<CXXRecordDecl>(Record);
+ CXXRecord->setAggregate(false);
+ CXXRecord->setPOD(false);
+ }
+
return NewFD;
}
return 0;
}
+ SetClassDeclAttributesFromBase(Class, CXXBaseDecl, Virtual);
+
if (BaseDecl->isInvalidDecl())
Class->setInvalidDecl();
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:
Base = Pattern->bases_begin(), BaseEnd = Pattern->bases_end();
Base != BaseEnd; ++Base) {
if (!Base->getType()->isDependentType()) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+
+ // Make sure to set the attributes from the base.
+ SetClassDeclAttributesFromBase(Instantiation, BaseDecl,
+ Base->isVirtual());
+
InstantiatedBases.push_back(new (Context) CXXBaseSpecifier(*Base));
continue;
}
if (InitFunctionInstantiation(New, Tmpl))
return true;
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner);
New->setAccess(Tmpl->getAccess());
if (Tmpl->isVirtualAsWritten())
- New->setVirtualAsWritten(true);
+ Record->setMethodAsVirtual(New);
// FIXME: attributes
// FIXME: New needs a pointer to Tmpl