]> granicus.if.org Git - clang/commitdiff
Temporarily revert 114929 114925 114924 114921. It looked like they (or at least
authorBill Wendling <isanbard@gmail.com>
Tue, 28 Sep 2010 01:09:49 +0000 (01:09 +0000)
committerBill Wendling <isanbard@gmail.com>
Tue, 28 Sep 2010 01:09:49 +0000 (01:09 +0000)
one of them) was causing a series of failures:

http://google1.osuosl.org:8011/builders/clang-x86_64-darwin10-selfhost/builds/4518

svn merge -c -114929 https://llvm.org/svn/llvm-project/cfe/trunk
--- Reverse-merging r114929 into '.':
U    include/clang/Sema/Sema.h
U    include/clang/AST/DeclCXX.h
U    lib/Sema/SemaDeclCXX.cpp
U    lib/Sema/SemaTemplateInstantiateDecl.cpp
U    lib/Sema/SemaDecl.cpp
U    lib/Sema/SemaTemplateInstantiate.cpp
U    lib/AST/DeclCXX.cpp
svn merge -c -114925 https://llvm.org/svn/llvm-project/cfe/trunk
--- Reverse-merging r114925 into '.':
G    include/clang/AST/DeclCXX.h
G    lib/Sema/SemaDeclCXX.cpp
G    lib/AST/DeclCXX.cpp
svn merge -c -114924 https://llvm.org/svn/llvm-project/cfe/trunk
--- Reverse-merging r114924 into '.':
G    include/clang/AST/DeclCXX.h
G    lib/Sema/SemaDeclCXX.cpp
G    lib/Sema/SemaDecl.cpp
G    lib/AST/DeclCXX.cpp
U    lib/AST/ASTContext.cpp
svn merge -c -114921 https://llvm.org/svn/llvm-project/cfe/trunk
--- Reverse-merging r114921 into '.':
G    include/clang/AST/DeclCXX.h
G    lib/Sema/SemaDeclCXX.cpp
G    lib/Sema/SemaDecl.cpp
G    lib/AST/DeclCXX.cpp

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114933 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclCXX.h
include/clang/Sema/Sema.h
lib/AST/ASTContext.cpp
lib/AST/DeclCXX.cpp
lib/CodeGen/CGBuiltin.cpp
lib/CodeGen/CodeGenFunction.h
lib/Headers/mmintrin.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp

index 786393cc3132174fcf44c34395450211e56835a8..975659b1e50e93a83aba4583cb53c2677124a83a 100644 (file)
@@ -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.
   ///
index 5445c1b755ab7e2717f98f8b8d2014ae4b991d06..5d8ead37dc4e0bf3af74613402d71ca4a2dcc03a 100644 (file)
@@ -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,
index 57780ef981cd742a9088e4d4380567c9b8da44a6..fdeac1ebf87b3cea9cefa705442979dd8694a622 100644 (file)
@@ -3138,6 +3138,10 @@ QualType ASTContext::getObjCFastEnumerationStateType() {
       Field->setAccess(AS_public);
       ObjCFastEnumerationStateTypeDecl->addDecl(Field);
     }
+    if (getLangOptions().CPlusPlus)
+      if (CXXRecordDecl *CXXRD = 
+            dyn_cast<CXXRecordDecl>(ObjCFastEnumerationStateTypeDecl))
+        CXXRD->setEmpty(false);
 
     ObjCFastEnumerationStateTypeDecl->completeDefinition();
   }
index 3e6d8b379ff4a942ca9ae87872abb051907a9218..5d9a09da702083fc779082c57417b3ab6da3aa23 100644 (file)
@@ -97,25 +97,6 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
     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(),
@@ -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<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
@@ -422,19 +334,6 @@ CXXRecordDecl::addedMember(Decl *D) {
   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;
   }
   
@@ -483,57 +382,6 @@ CXXRecordDecl::addedMember(Decl *D) {
     
     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) {
@@ -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<CXXRecordDecl>(MSInfo->getInstantiatedFrom());
index 443b7c089f56f85dca282fcb1915594bb2321dfb..1dd9b4365b76ca755a23678bfa4083df92c4a130 100644 (file)
@@ -1869,6 +1869,33 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
   }
 }
 
+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) {
 
@@ -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<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();
     
index 8dc8ac1e3d2c5c01de3a3923c5c3afa32b5aad0a..8298443b6c81100b0ff8b66b3b56979a8d72a741 100644 (file)
@@ -536,6 +536,9 @@ public:
 
   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.
index bad9e1c059dcfb29d391a9654b2035cb4142e26c..fefb42fd74e3c4c1278c39ec69ea926c98c9322d 100644 (file)
@@ -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);
 }
 
 
index c189bce8ebfb23ddd5fbc8e1c0bfb1094e13249d..68cdc556e8d56c0a1ad9da8a096be8fc3b62ae8c 100644 (file)
@@ -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<FieldDecl>(Anon));
+      if (!cast<CXXRecordDecl>(Record)->isEmpty())
+        cast<CXXRecordDecl>(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<CXXRecordDecl>(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<CXXConversionDecl>(NewFD)) {
       ActOnConversionDeclarator(Conversion);
@@ -6179,9 +6192,27 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
   }
 
   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
@@ -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<CXXRecordDecl>(Record);
+    CXXRecord->setAggregate(false);
+    CXXRecord->setPOD(false);
+  }
+
   return NewFD;
 }
 
index 63acb095a663b9a9380d42d07fb4abbdebe4be0d..473247139e65463db494eb9a0fdeb0b55e142bb4 100644 (file)
@@ -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:
index a2c3df653b7a0d1bfc0c4a940a863cacb413b714..5520f6404478a58a5ed8cbdb7671e2175ec5b39a 100644 (file)
@@ -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<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;
     }
index d87629151ebe59492e2f8ac18788f0a04ac0ee93..f9ff20463abaeec49202dd8874330f3d6863a443 100644 (file)
@@ -1996,9 +1996,10 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
   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