зеркало из https://github.com/microsoft/clang.git
Temporarily revert 114929 114925 114924 114921. It looked like they (or at least
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
This commit is contained in:
Родитель
e10288c1e9
Коммит
2a674e8e44
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче