diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST')
23 files changed, 1446 insertions, 685 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/APValue.cpp b/contrib/llvm/tools/clang/lib/AST/APValue.cpp index 731d5e0..ebe99b1 100644 --- a/contrib/llvm/tools/clang/lib/AST/APValue.cpp +++ b/contrib/llvm/tools/clang/lib/AST/APValue.cpp @@ -18,12 +18,12 @@ using namespace clang; namespace { struct LV { - Expr* Base; + const Expr* Base; CharUnits Offset; }; } -APValue::APValue(Expr* B) : Kind(Uninitialized) { +APValue::APValue(const Expr* B) : Kind(Uninitialized) { MakeLValue(); setLValue(B, CharUnits::Zero()); } @@ -118,7 +118,7 @@ void APValue::print(llvm::raw_ostream &OS) const { } } -Expr* APValue::getLValueBase() const { +const Expr* APValue::getLValueBase() const { assert(isLValue() && "Invalid accessor"); return ((const LV*)(const void*)Data)->Base; } @@ -128,7 +128,7 @@ CharUnits APValue::getLValueOffset() const { return ((const LV*)(const void*)Data)->Offset; } -void APValue::setLValue(Expr *B, const CharUnits &O) { +void APValue::setLValue(const Expr *B, const CharUnits &O) { assert(isLValue() && "Invalid accessor"); ((LV*)(char*)Data)->Base = B; ((LV*)(char*)Data)->Offset = O; diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp index 8316ea6..9094aba 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp @@ -31,6 +31,7 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include "CXXABI.h" +#include <map> using namespace clang; @@ -38,8 +39,12 @@ unsigned ASTContext::NumImplicitDefaultConstructors; unsigned ASTContext::NumImplicitDefaultConstructorsDeclared; unsigned ASTContext::NumImplicitCopyConstructors; unsigned ASTContext::NumImplicitCopyConstructorsDeclared; +unsigned ASTContext::NumImplicitMoveConstructors; +unsigned ASTContext::NumImplicitMoveConstructorsDeclared; unsigned ASTContext::NumImplicitCopyAssignmentOperators; unsigned ASTContext::NumImplicitCopyAssignmentOperatorsDeclared; +unsigned ASTContext::NumImplicitMoveAssignmentOperators; +unsigned ASTContext::NumImplicitMoveAssignmentOperatorsDeclared; unsigned ASTContext::NumImplicitDestructors; unsigned ASTContext::NumImplicitDestructorsDeclared; @@ -317,9 +322,17 @@ void ASTContext::PrintStats() const { fprintf(stderr, " %u/%u implicit copy constructors created\n", NumImplicitCopyConstructorsDeclared, NumImplicitCopyConstructors); + if (getLangOptions().CPlusPlus) + fprintf(stderr, " %u/%u implicit move constructors created\n", + NumImplicitMoveConstructorsDeclared, + NumImplicitMoveConstructors); fprintf(stderr, " %u/%u implicit copy assignment operators created\n", NumImplicitCopyAssignmentOperatorsDeclared, NumImplicitCopyAssignmentOperators); + if (getLangOptions().CPlusPlus) + fprintf(stderr, " %u/%u implicit move assignment operators created\n", + NumImplicitMoveAssignmentOperatorsDeclared, + NumImplicitMoveAssignmentOperators); fprintf(stderr, " %u/%u implicit destructors created\n", NumImplicitDestructorsDeclared, NumImplicitDestructors); @@ -546,8 +559,28 @@ bool ASTContext::ZeroBitfieldFollowsNonBitfield(const FieldDecl *FD, bool ASTContext::ZeroBitfieldFollowsBitfield(const FieldDecl *FD, const FieldDecl *LastFD) const { return (FD->isBitField() && LastFD && LastFD->isBitField() && - FD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue() == 0); + FD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue() == 0 && + LastFD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue() != 0); + +} +bool ASTContext::BitfieldFollowsBitfield(const FieldDecl *FD, + const FieldDecl *LastFD) const { + return (FD->isBitField() && LastFD && LastFD->isBitField() && + FD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue() && + LastFD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue()); +} + +bool ASTContext::NoneBitfieldFollowsBitfield(const FieldDecl *FD, + const FieldDecl *LastFD) const { + return (!FD->isBitField() && LastFD && LastFD->isBitField() && + LastFD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue()); +} + +bool ASTContext::BitfieldFollowsNoneBitfield(const FieldDecl *FD, + const FieldDecl *LastFD) const { + return (FD->isBitField() && LastFD && !LastFD->isBitField() && + FD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue()); } ASTContext::overridden_cxx_method_iterator @@ -627,6 +660,10 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const { UseAlignAttrOnly = true; } } + else if (isa<FieldDecl>(D)) + UseAlignAttrOnly = + D->hasAttr<PackedAttr>() || + cast<FieldDecl>(D)->getParent()->hasAttr<PackedAttr>(); // If we're using the align attribute only, just ignore everything // else about the declaration and its type. @@ -950,6 +987,9 @@ ASTContext::getTypeInfo(const Type *T) const { return getTypeInfo(cast<DecltypeType>(T)->getUnderlyingExpr()->getType() .getTypePtr()); + case Type::UnaryTransform: + return getTypeInfo(cast<UnaryTransformType>(T)->getUnderlyingType()); + case Type::Elaborated: return getTypeInfo(cast<ElaboratedType>(T)->getNamedType().getTypePtr()); @@ -957,13 +997,18 @@ ASTContext::getTypeInfo(const Type *T) const { return getTypeInfo( cast<AttributedType>(T)->getEquivalentType().getTypePtr()); - case Type::TemplateSpecialization: + case Type::TemplateSpecialization: { assert(getCanonicalType(T) != T && "Cannot request the size of a dependent type"); - // FIXME: this is likely to be wrong once we support template - // aliases, since a template alias could refer to a typedef that - // has an __aligned__ attribute on it. - return getTypeInfo(getCanonicalType(T)); + const TemplateSpecializationType *TST = cast<TemplateSpecializationType>(T); + // A type alias template specialization may refer to a typedef with the + // aligned attribute on it. + if (TST->isTypeAlias()) + return getTypeInfo(TST->getAliasedType().getTypePtr()); + else + return getTypeInfo(getCanonicalType(T)); + } + } assert(Align && (Align & (Align-1)) == 0 && "Alignment must be power of 2"); @@ -1393,6 +1438,9 @@ QualType ASTContext::getBlockPointerType(QualType T) const { /// lvalue reference to the specified type. QualType ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) const { + assert(getCanonicalType(T) != OverloadTy && + "Unresolved overloaded function type"); + // Unique pointers, to guarantee there is only one pointer of a particular // structure. llvm::FoldingSetNodeID ID; @@ -1572,6 +1620,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { case Type::TypeOfExpr: case Type::TypeOf: case Type::Decltype: + case Type::UnaryTransform: case Type::DependentName: case Type::InjectedClassName: case Type::TemplateSpecialization: @@ -2235,10 +2284,10 @@ TypeSourceInfo * ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name, SourceLocation NameLoc, const TemplateArgumentListInfo &Args, - QualType CanonType) const { + QualType Underlying) const { assert(!Name.getAsDependentTemplateName() && "No dependent template names here!"); - QualType TST = getTemplateSpecializationType(Name, Args, CanonType); + QualType TST = getTemplateSpecializationType(Name, Args, Underlying); TypeSourceInfo *DI = CreateTypeSourceInfo(TST); TemplateSpecializationTypeLoc TL @@ -2254,7 +2303,7 @@ ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name, QualType ASTContext::getTemplateSpecializationType(TemplateName Template, const TemplateArgumentListInfo &Args, - QualType Canon) const { + QualType Underlying) const { assert(!Template.getAsDependentTemplateName() && "No dependent template names here!"); @@ -2266,35 +2315,46 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, ArgVec.push_back(Args[i].getArgument()); return getTemplateSpecializationType(Template, ArgVec.data(), NumArgs, - Canon); + Underlying); } QualType ASTContext::getTemplateSpecializationType(TemplateName Template, const TemplateArgument *Args, unsigned NumArgs, - QualType Canon) const { + QualType Underlying) const { assert(!Template.getAsDependentTemplateName() && "No dependent template names here!"); // Look through qualified template names. if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) Template = TemplateName(QTN->getTemplateDecl()); - if (!Canon.isNull()) - Canon = getCanonicalType(Canon); - else - Canon = getCanonicalTemplateSpecializationType(Template, Args, NumArgs); + bool isTypeAlias = + Template.getAsTemplateDecl() && + isa<TypeAliasTemplateDecl>(Template.getAsTemplateDecl()); + + QualType CanonType; + if (!Underlying.isNull()) + CanonType = getCanonicalType(Underlying); + else { + assert(!isTypeAlias && + "Underlying type for template alias must be computed by caller"); + CanonType = getCanonicalTemplateSpecializationType(Template, Args, + NumArgs); + } // Allocate the (non-canonical) template specialization type, but don't // try to unique it: these types typically have location information that // we don't unique and don't want to lose. - void *Mem = Allocate((sizeof(TemplateSpecializationType) + - sizeof(TemplateArgument) * NumArgs), + void *Mem = Allocate(sizeof(TemplateSpecializationType) + + sizeof(TemplateArgument) * NumArgs + + (isTypeAlias ? sizeof(QualType) : 0), TypeAlignment); TemplateSpecializationType *Spec = new (Mem) TemplateSpecializationType(Template, Args, NumArgs, - Canon); + CanonType, + isTypeAlias ? Underlying : QualType()); Types.push_back(Spec); return QualType(Spec, 0); @@ -2306,6 +2366,10 @@ ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template, unsigned NumArgs) const { assert(!Template.getAsDependentTemplateName() && "No dependent template names here!"); + assert((!Template.getAsTemplateDecl() || + !isa<TypeAliasTemplateDecl>(Template.getAsTemplateDecl())) && + "Underlying type for template alias must be computed by caller"); + // Look through qualified template names. if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) Template = TemplateName(QTN->getTemplateDecl()); @@ -2334,7 +2398,7 @@ ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template, TypeAlignment); Spec = new (Mem) TemplateSpecializationType(CanonTemplate, CanonArgs.data(), NumArgs, - QualType()); + QualType(), QualType()); Types.push_back(Spec); TemplateSpecializationTypes.InsertNode(Spec, InsertPos); } @@ -2754,6 +2818,21 @@ QualType ASTContext::getDecltypeType(Expr *e) const { return QualType(dt, 0); } +/// getUnaryTransformationType - We don't unique these, since the memory +/// savings are minimal and these are rare. +QualType ASTContext::getUnaryTransformType(QualType BaseType, + QualType UnderlyingType, + UnaryTransformType::UTTKind Kind) + const { + UnaryTransformType *Ty = + new (*this, TypeAlignment) UnaryTransformType (BaseType, UnderlyingType, + Kind, + UnderlyingType->isDependentType() ? + QualType() : UnderlyingType); + Types.push_back(Ty); + return QualType(Ty, 0); +} + /// getAutoType - We only unique auto types after they've been deduced. QualType ASTContext::getAutoType(QualType DeducedType) const { void *InsertPos = 0; @@ -3457,7 +3536,8 @@ QualType ASTContext::getCFConstantStringType() const { SourceLocation(), 0, FieldTypes[i], /*TInfo=*/0, /*BitWidth=*/0, - /*Mutable=*/false); + /*Mutable=*/false, + /*HasInit=*/false); Field->setAccess(AS_public); CFConstantStringTypeDecl->addDecl(Field); } @@ -3498,7 +3578,8 @@ QualType ASTContext::getNSConstantStringType() const { SourceLocation(), 0, FieldTypes[i], /*TInfo=*/0, /*BitWidth=*/0, - /*Mutable=*/false); + /*Mutable=*/false, + /*HasInit=*/false); Field->setAccess(AS_public); NSConstantStringTypeDecl->addDecl(Field); } @@ -3537,7 +3618,8 @@ QualType ASTContext::getObjCFastEnumerationStateType() const { SourceLocation(), 0, FieldTypes[i], /*TInfo=*/0, /*BitWidth=*/0, - /*Mutable=*/false); + /*Mutable=*/false, + /*HasInit=*/false); Field->setAccess(AS_public); ObjCFastEnumerationStateTypeDecl->addDecl(Field); } @@ -3574,7 +3656,8 @@ QualType ASTContext::getBlockDescriptorType() const { &Idents.get(FieldNames[i]), FieldTypes[i], /*TInfo=*/0, /*BitWidth=*/0, - /*Mutable=*/false); + /*Mutable=*/false, + /*HasInit=*/false); Field->setAccess(AS_public); T->addDecl(Field); } @@ -3622,7 +3705,8 @@ QualType ASTContext::getBlockDescriptorExtendedType() const { &Idents.get(FieldNames[i]), FieldTypes[i], /*TInfo=*/0, /*BitWidth=*/0, - /*Mutable=*/false); + /*Mutable=*/false, + /*HasInit=*/false); Field->setAccess(AS_public); T->addDecl(Field); } @@ -3650,7 +3734,7 @@ bool ASTContext::BlockRequiresCopying(QualType Ty) const { if (getLangOptions().CPlusPlus) { if (const RecordType *RT = Ty->getAs<RecordType>()) { CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - return RD->hasConstCopyConstructor(*this); + return RD->hasConstCopyConstructor(); } } @@ -3707,7 +3791,8 @@ ASTContext::BuildByRefType(llvm::StringRef DeclName, QualType Ty) const { SourceLocation(), &Idents.get(FieldNames[i]), FieldTypes[i], /*TInfo=*/0, - /*BitWidth=*/0, /*Mutable=*/false); + /*BitWidth=*/0, /*Mutable=*/false, + /*HasInit=*/false); Field->setAccess(AS_public); T->addDecl(Field); } @@ -3736,6 +3821,9 @@ static bool isTypeTypedefedAsBOOL(QualType T) { /// getObjCEncodingTypeSize returns size of type for objective-c encoding /// purpose. CharUnits ASTContext::getObjCEncodingTypeSize(QualType type) const { + if (!type->isIncompleteArrayType() && type->isIncompleteType()) + return CharUnits::Zero(); + CharUnits sz = getTypeSizeInChars(type); // Make all integer and enum types at least as large as an int @@ -3803,7 +3891,7 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const { return S; } -void ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, +bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, std::string& S) { // Encode result type. getObjCEncodingForType(Decl->getResultType(), S); @@ -3813,8 +3901,11 @@ void ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, E = Decl->param_end(); PI != E; ++PI) { QualType PType = (*PI)->getType(); CharUnits sz = getObjCEncodingTypeSize(PType); + if (sz.isZero()) + return true; + assert (sz.isPositive() && - "getObjCEncodingForMethodDecl - Incomplete param type"); + "getObjCEncodingForFunctionDecl - Incomplete param type"); ParmOffset += sz; } S += charUnitsToString(ParmOffset); @@ -3837,11 +3928,13 @@ void ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, S += charUnitsToString(ParmOffset); ParmOffset += getObjCEncodingTypeSize(PType); } + + return false; } /// getObjCEncodingForMethodDecl - Return the encoded type for this method /// declaration. -void ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, +bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string& S) const { // FIXME: This is not very efficient. // Encode type qualifer, 'in', 'inout', etc. for the return type. @@ -3860,6 +3953,9 @@ void ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, E = Decl->sel_param_end(); PI != E; ++PI) { QualType PType = (*PI)->getType(); CharUnits sz = getObjCEncodingTypeSize(PType); + if (sz.isZero()) + return true; + assert (sz.isPositive() && "getObjCEncodingForMethodDecl - Incomplete param type"); ParmOffset += sz; @@ -3889,6 +3985,8 @@ void ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, S += charUnitsToString(ParmOffset); ParmOffset += getObjCEncodingTypeSize(PType); } + + return false; } /// getObjCEncodingForPropertyDecl - Return the encoded type for this @@ -4108,7 +4206,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, bool ExpandStructures, const FieldDecl *FD, bool OutermostType, - bool EncodingProperty) const { + bool EncodingProperty, + bool StructField) const { if (T->getAs<BuiltinType>()) { if (FD && FD->isBitField()) return EncodeBitField(this, S, T, FD); @@ -4193,7 +4292,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, if (const ArrayType *AT = // Ignore type qualifiers etc. dyn_cast<ArrayType>(T->getCanonicalTypeInternal())) { - if (isa<IncompleteArrayType>(AT)) { + if (isa<IncompleteArrayType>(AT) && !StructField) { // Incomplete arrays are encoded as a pointer to the array element. S += '^'; @@ -4202,11 +4301,15 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, } else { S += '['; - if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) - S += llvm::utostr(CAT->getSize().getZExtValue()); - else { + if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) { + if (getTypeSize(CAT->getElementType()) == 0) + S += '0'; + else + S += llvm::utostr(CAT->getSize().getZExtValue()); + } else { //Variable length arrays are encoded as a regular array with 0 elements. - assert(isa<VariableArrayType>(AT) && "Unknown array type!"); + assert((isa<VariableArrayType>(AT) || isa<IncompleteArrayType>(AT)) && + "Unknown array type!"); S += '0'; } @@ -4244,24 +4347,30 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, } if (ExpandStructures) { S += '='; - for (RecordDecl::field_iterator Field = RDecl->field_begin(), - FieldEnd = RDecl->field_end(); - Field != FieldEnd; ++Field) { - if (FD) { - S += '"'; - S += Field->getNameAsString(); - S += '"'; - } + if (!RDecl->isUnion()) { + getObjCEncodingForStructureImpl(RDecl, S, FD); + } else { + for (RecordDecl::field_iterator Field = RDecl->field_begin(), + FieldEnd = RDecl->field_end(); + Field != FieldEnd; ++Field) { + if (FD) { + S += '"'; + S += Field->getNameAsString(); + S += '"'; + } - // Special case bit-fields. - if (Field->isBitField()) { - getObjCEncodingForTypeImpl(Field->getType(), S, false, true, - (*Field)); - } else { - QualType qt = Field->getType(); - getLegacyIntegralTypeEncoding(qt); - getObjCEncodingForTypeImpl(qt, S, false, true, - FD); + // Special case bit-fields. + if (Field->isBitField()) { + getObjCEncodingForTypeImpl(Field->getType(), S, false, true, + (*Field)); + } else { + QualType qt = Field->getType(); + getLegacyIntegralTypeEncoding(qt); + getObjCEncodingForTypeImpl(qt, S, false, true, + FD, /*OutermostType*/false, + /*EncodingProperty*/false, + /*StructField*/true); + } } } } @@ -4382,6 +4491,135 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, assert(0 && "@encode for type not implemented!"); } +void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, + std::string &S, + const FieldDecl *FD, + bool includeVBases) const { + assert(RDecl && "Expected non-null RecordDecl"); + assert(!RDecl->isUnion() && "Should not be called for unions"); + if (!RDecl->getDefinition()) + return; + + CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(RDecl); + std::multimap<uint64_t, NamedDecl *> FieldOrBaseOffsets; + const ASTRecordLayout &layout = getASTRecordLayout(RDecl); + + if (CXXRec) { + for (CXXRecordDecl::base_class_iterator + BI = CXXRec->bases_begin(), + BE = CXXRec->bases_end(); BI != BE; ++BI) { + if (!BI->isVirtual()) { + CXXRecordDecl *base = BI->getType()->getAsCXXRecordDecl(); + uint64_t offs = layout.getBaseClassOffsetInBits(base); + FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs), + std::make_pair(offs, base)); + } + } + } + + unsigned i = 0; + for (RecordDecl::field_iterator Field = RDecl->field_begin(), + FieldEnd = RDecl->field_end(); + Field != FieldEnd; ++Field, ++i) { + uint64_t offs = layout.getFieldOffset(i); + FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs), + std::make_pair(offs, *Field)); + } + + if (CXXRec && includeVBases) { + for (CXXRecordDecl::base_class_iterator + BI = CXXRec->vbases_begin(), + BE = CXXRec->vbases_end(); BI != BE; ++BI) { + CXXRecordDecl *base = BI->getType()->getAsCXXRecordDecl(); + uint64_t offs = layout.getVBaseClassOffsetInBits(base); + FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs), + std::make_pair(offs, base)); + } + } + + CharUnits size; + if (CXXRec) { + size = includeVBases ? layout.getSize() : layout.getNonVirtualSize(); + } else { + size = layout.getSize(); + } + + uint64_t CurOffs = 0; + std::multimap<uint64_t, NamedDecl *>::iterator + CurLayObj = FieldOrBaseOffsets.begin(); + + if (CurLayObj != FieldOrBaseOffsets.end() && CurLayObj->first != 0) { + assert(CXXRec && CXXRec->isDynamicClass() && + "Offset 0 was empty but no VTable ?"); + if (FD) { + S += "\"_vptr$"; + std::string recname = CXXRec->getNameAsString(); + if (recname.empty()) recname = "?"; + S += recname; + S += '"'; + } + S += "^^?"; + CurOffs += getTypeSize(VoidPtrTy); + } + + if (!RDecl->hasFlexibleArrayMember()) { + // Mark the end of the structure. + uint64_t offs = toBits(size); + FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs), + std::make_pair(offs, (NamedDecl*)0)); + } + + for (; CurLayObj != FieldOrBaseOffsets.end(); ++CurLayObj) { + assert(CurOffs <= CurLayObj->first); + + if (CurOffs < CurLayObj->first) { + uint64_t padding = CurLayObj->first - CurOffs; + // FIXME: There doesn't seem to be a way to indicate in the encoding that + // packing/alignment of members is different that normal, in which case + // the encoding will be out-of-sync with the real layout. + // If the runtime switches to just consider the size of types without + // taking into account alignment, we could make padding explicit in the + // encoding (e.g. using arrays of chars). The encoding strings would be + // longer then though. + CurOffs += padding; + } + + NamedDecl *dcl = CurLayObj->second; + if (dcl == 0) + break; // reached end of structure. + + if (CXXRecordDecl *base = dyn_cast<CXXRecordDecl>(dcl)) { + // We expand the bases without their virtual bases since those are going + // in the initial structure. Note that this differs from gcc which + // expands virtual bases each time one is encountered in the hierarchy, + // making the encoding type bigger than it really is. + getObjCEncodingForStructureImpl(base, S, FD, /*includeVBases*/false); + if (!base->isEmpty()) + CurOffs += toBits(getASTRecordLayout(base).getNonVirtualSize()); + } else { + FieldDecl *field = cast<FieldDecl>(dcl); + if (FD) { + S += '"'; + S += field->getNameAsString(); + S += '"'; + } + + if (field->isBitField()) { + EncodeBitField(this, S, field->getType(), field); + CurOffs += field->getBitWidth()->EvaluateAsInt(*this).getZExtValue(); + } else { + QualType qt = field->getType(); + getLegacyIntegralTypeEncoding(qt); + getObjCEncodingForTypeImpl(qt, S, false, true, FD, + /*OutermostType*/false, + /*EncodingProperty*/false, + /*StructField*/true); + CurOffs += getTypeSize(field->getType()); + } + } + } +} + void ASTContext::getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT, std::string& S) const { if (QT & Decl::OBJC_TQ_In) @@ -6068,7 +6306,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { // Forward declarations aren't required. - if (!FD->isThisDeclarationADefinition()) + if (!FD->doesThisDeclarationHaveABody()) return false; // Constructors and destructors are required. @@ -6105,10 +6343,13 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { // Structs that have non-trivial constructors or destructors are required. // FIXME: Handle references. + // FIXME: Be more selective about which constructors we care about. if (const RecordType *RT = VD->getType()->getAs<RecordType>()) { if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) { - if (RD->hasDefinition() && - (!RD->hasTrivialConstructor() || !RD->hasTrivialDestructor())) + if (RD->hasDefinition() && !(RD->hasTrivialDefaultConstructor() && + RD->hasTrivialCopyConstructor() && + RD->hasTrivialMoveConstructor() && + RD->hasTrivialDestructor())) return true; } } diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp index 897b4a4..16d2f85 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp @@ -56,9 +56,11 @@ static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) { continue; } - // Don't desugar template specializations. - if (isa<TemplateSpecializationType>(Ty)) - break; + // Don't desugar template specializations, unless it's an alias template. + if (const TemplateSpecializationType *TST + = dyn_cast<TemplateSpecializationType>(Ty)) + if (!TST->isTypeAlias()) + break; // Don't desugar magic Objective-C types. if (QualType(Ty,0) == Context.getObjCIdType() || diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp index dc881ba..100e604 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp @@ -64,6 +64,7 @@ namespace { // FIXME: DependentTypeOfExprType QualType VisitTypeOfType(const TypeOfType *T); QualType VisitDecltypeType(const DecltypeType *T); + QualType VisitUnaryTransformType(const UnaryTransformType *T); QualType VisitAutoType(const AutoType *T); // FIXME: DependentDecltypeType QualType VisitRecordType(const RecordType *T); @@ -604,7 +605,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, cast<TypeOfType>(T2)->getUnderlyingType())) return false; break; - + + case Type::UnaryTransform: + if (!IsStructurallyEquivalent(Context, + cast<UnaryTransformType>(T1)->getUnderlyingType(), + cast<UnaryTransformType>(T1)->getUnderlyingType())) + return false; + break; + case Type::Decltype: if (!IsStructurallyEquivalent(Context, cast<DecltypeType>(T1)->getUnderlyingExpr(), @@ -1572,6 +1580,17 @@ QualType ASTNodeImporter::VisitDecltypeType(const DecltypeType *T) { return Importer.getToContext().getDecltypeType(ToExpr); } +QualType ASTNodeImporter::VisitUnaryTransformType(const UnaryTransformType *T) { + QualType ToBaseType = Importer.Import(T->getBaseType()); + QualType ToUnderlyingType = Importer.Import(T->getUnderlyingType()); + if (ToBaseType.isNull() || ToUnderlyingType.isNull()) + return QualType(); + + return Importer.getToContext().getUnaryTransformType(ToBaseType, + ToUnderlyingType, + T->getUTTKind()); +} + QualType ASTNodeImporter::VisitAutoType(const AutoType *T) { // FIXME: Make sure that the "to" context supports C++0x! QualType FromDeduced = T->getDeducedType(); @@ -2493,9 +2512,12 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { FieldDecl *ToField = FieldDecl::Create(Importer.getToContext(), DC, Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(), - T, TInfo, BitWidth, D->isMutable()); + T, TInfo, BitWidth, D->isMutable(), + D->hasInClassInitializer()); ToField->setAccess(D->getAccess()); ToField->setLexicalDeclContext(LexicalDC); + if (ToField->hasInClassInitializer()) + ToField->setInClassInitializer(D->getInClassInitializer()); Importer.Imported(D, ToField); LexicalDC->addDecl(ToField); return ToField; @@ -2851,7 +2873,8 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { D->isVariadic(), D->isSynthesized(), D->isDefined(), - D->getImplementationControl()); + D->getImplementationControl(), + D->hasRelatedResultType()); // FIXME: When we decide to merge method definitions, we'll need to // deal with implicit parameters. diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp index b21ba9a..12357c0 100644 --- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp @@ -1422,6 +1422,31 @@ bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const { return false; } +bool FunctionDecl::hasTrivialBody() const +{ + Stmt *S = getBody(); + if (!S) { + // Since we don't have a body for this function, we don't know if it's + // trivial or not. + return false; + } + + if (isa<CompoundStmt>(S) && cast<CompoundStmt>(S)->body_empty()) + return true; + return false; +} + +bool FunctionDecl::isDefined(const FunctionDecl *&Definition) const { + for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { + if (I->IsDeleted || I->IsDefaulted || I->Body || I->IsLateTemplateParsed) { + Definition = I->IsDeleted ? I->getCanonicalDecl() : *I; + return true; + } + } + + return false; +} + Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { if (I->Body) { @@ -1450,10 +1475,34 @@ void FunctionDecl::setPure(bool P) { } bool FunctionDecl::isMain() const { - ASTContext &Context = getASTContext(); - return !Context.getLangOptions().Freestanding && - getDeclContext()->getRedeclContext()->isTranslationUnit() && - getIdentifier() && getIdentifier()->isStr("main"); + const TranslationUnitDecl *tunit = + dyn_cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext()); + return tunit && + !tunit->getASTContext().getLangOptions().Freestanding && + getIdentifier() && + getIdentifier()->isStr("main"); +} + +bool FunctionDecl::isReservedGlobalPlacementOperator() const { + assert(getDeclName().getNameKind() == DeclarationName::CXXOperatorName); + assert(getDeclName().getCXXOverloadedOperator() == OO_New || + getDeclName().getCXXOverloadedOperator() == OO_Delete || + getDeclName().getCXXOverloadedOperator() == OO_Array_New || + getDeclName().getCXXOverloadedOperator() == OO_Array_Delete); + + if (isa<CXXRecordDecl>(getDeclContext())) return false; + assert(getDeclContext()->getRedeclContext()->isTranslationUnit()); + + const FunctionProtoType *proto = getType()->castAs<FunctionProtoType>(); + if (proto->getNumArgs() != 2 || proto->isVariadic()) return false; + + ASTContext &Context = + cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext()) + ->getASTContext(); + + // The result type and first argument type are constant across all + // these operators. The second argument must be exactly void*. + return (proto->getArgType(1).getCanonicalType() == Context.VoidPtrTy); } bool FunctionDecl::isExternC() const { @@ -1690,11 +1739,11 @@ bool FunctionDecl::isInlined() const { /// an externally visible symbol, but "extern inline" will not create an /// externally visible symbol. bool FunctionDecl::isInlineDefinitionExternallyVisible() const { - assert(isThisDeclarationADefinition() && "Must have the function definition"); + assert(doesThisDeclarationHaveABody() && "Must have the function definition"); assert(isInlined() && "Function must be inline"); ASTContext &Context = getASTContext(); - if (!Context.getLangOptions().C99 || hasAttr<GNUInlineAttr>()) { + if (Context.getLangOptions().GNUInline || hasAttr<GNUInlineAttr>()) { // If it's not the case that both 'inline' and 'extern' are // specified on the definition, then this inline definition is // externally visible. @@ -2028,9 +2077,10 @@ SourceRange FunctionDecl::getSourceRange() const { FieldDecl *FieldDecl::Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, - TypeSourceInfo *TInfo, Expr *BW, bool Mutable) { + TypeSourceInfo *TInfo, Expr *BW, bool Mutable, + bool HasInit) { return new (C) FieldDecl(Decl::Field, DC, StartLoc, IdLoc, Id, T, TInfo, - BW, Mutable); + BW, Mutable, HasInit); } bool FieldDecl::isAnonymousStructOrUnion() const { @@ -2059,8 +2109,7 @@ unsigned FieldDecl::getFieldIndex() const { if (IsMsStruct) { // Zero-length bitfields following non-bitfield members are ignored. - if (getASTContext().ZeroBitfieldFollowsNonBitfield((*i), LastFD) || - getASTContext().ZeroBitfieldFollowsBitfield((*i), LastFD)) { + if (getASTContext().ZeroBitfieldFollowsNonBitfield((*i), LastFD)) { ++i; continue; } @@ -2076,10 +2125,17 @@ unsigned FieldDecl::getFieldIndex() const { SourceRange FieldDecl::getSourceRange() const { if (isBitField()) - return SourceRange(getInnerLocStart(), BitWidth->getLocEnd()); + return SourceRange(getInnerLocStart(), getBitWidth()->getLocEnd()); return DeclaratorDecl::getSourceRange(); } +void FieldDecl::setInClassInitializer(Expr *Init) { + assert(!InitializerOrBitWidth.getPointer() && + "bit width or initializer already set"); + InitializerOrBitWidth.setPointer(Init); + InitializerOrBitWidth.setInt(0); +} + //===----------------------------------------------------------------------===// // TagDecl Implementation //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp index 6d517c5..1766d39 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp @@ -439,6 +439,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case Typedef: case TypeAlias: + case TypeAliasTemplate: case UnresolvedUsingTypename: case TemplateTypeParm: return IDNS_Ordinary | IDNS_Type; @@ -1165,10 +1166,10 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) { if (!D->getDeclName()) return; - // FIXME: This feels like a hack. Should DeclarationName support - // template-ids, or is there a better way to keep specializations - // from being visible? - if (isa<ClassTemplateSpecializationDecl>(D) || D->isTemplateParameter()) + // Skip entities that can't be found by name lookup into a particular + // context. + if ((D->getIdentifierNamespace() == 0 && !isa<UsingDirectiveDecl>(D)) || + D->isTemplateParameter()) return; ASTContext *C = 0; diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp index 9099cd5..08ac2a5 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp @@ -29,19 +29,21 @@ using namespace clang; CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) : UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false), - UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false), + UserDeclaredMoveConstructor(false), UserDeclaredCopyAssignment(false), + UserDeclaredMoveAssignment(false), UserDeclaredDestructor(false), Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false), Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true), HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false), - HasTrivialConstructor(true), HasConstExprNonCopyMoveConstructor(false), - HasTrivialCopyConstructor(true), HasTrivialMoveConstructor(true), - HasTrivialCopyAssignment(true), HasTrivialMoveAssignment(true), - HasTrivialDestructor(true), HasNonLiteralTypeFieldsOrBases(false), - ComputedVisibleConversions(false), - DeclaredDefaultConstructor(false), DeclaredCopyConstructor(false), - DeclaredCopyAssignment(false), DeclaredDestructor(false), - NumBases(0), NumVBases(0), Bases(), VBases(), - Definition(D), FirstFriend(0) { + HasMutableFields(false), HasTrivialDefaultConstructor(true), + HasConstExprNonCopyMoveConstructor(false), HasTrivialCopyConstructor(true), + HasTrivialMoveConstructor(true), HasTrivialCopyAssignment(true), + HasTrivialMoveAssignment(true), HasTrivialDestructor(true), + HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false), + UserProvidedDefaultConstructor(false), DeclaredDefaultConstructor(false), + DeclaredCopyConstructor(false), DeclaredMoveConstructor(false), + DeclaredCopyAssignment(false), DeclaredMoveAssignment(false), + DeclaredDestructor(false), NumBases(0), NumVBases(0), Bases(), VBases(), + Definition(D), FirstFriend(0) { } CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, @@ -165,8 +167,9 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, data().Empty = false; // C++ [class.ctor]p5: - // A constructor is trivial if its class has no virtual base classes. - data().HasTrivialConstructor = false; + // A default constructor is trivial [...] if: + // -- its class has [...] no virtual bases + data().HasTrivialDefaultConstructor = false; // C++0x [class.copy]p13: // A copy/move constructor for class X is trivial if it is neither @@ -188,10 +191,11 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, data().IsStandardLayout = 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; + // A default constructor is trivial [...] if: + // -- all the direct base classes of its class have trivial default + // constructors. + if (!BaseClassDecl->hasTrivialDefaultConstructor()) + data().HasTrivialDefaultConstructor = false; // C++0x [class.copy]p13: // A copy/move constructor for class X is trivial if [...] @@ -223,6 +227,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // have trivial destructors. if (!BaseClassDecl->hasTrivialDestructor()) data().HasTrivialDestructor = false; + + // Keep track of the presence of mutable fields. + if (BaseClassDecl->hasMutableFields()) + data().HasMutableFields = true; } if (VBases.empty()) @@ -262,8 +270,8 @@ bool CXXRecordDecl::hasAnyDependentBases() const { return !forallBases(SawBase, 0); } -bool CXXRecordDecl::hasConstCopyConstructor(const ASTContext &Context) const { - return getCopyConstructor(Context, Qualifiers::Const) != 0; +bool CXXRecordDecl::hasConstCopyConstructor() const { + return getCopyConstructor(Qualifiers::Const) != 0; } bool CXXRecordDecl::isTriviallyCopyable() const { @@ -306,8 +314,8 @@ GetBestOverloadCandidateSimple( return Cands[Best].first; } -CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(const ASTContext &Context, - unsigned TypeQuals) const{ +CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(unsigned TypeQuals) const{ + ASTContext &Context = getASTContext(); QualType ClassType = Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this)); DeclarationName ConstructorName @@ -337,6 +345,14 @@ CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(const ASTContext &Context, GetBestOverloadCandidateSimple(Found)); } +CXXConstructorDecl *CXXRecordDecl::getMoveConstructor() const { + for (ctor_iterator I = ctor_begin(), E = ctor_end(); I != E; ++I) + if (I->isMoveConstructor()) + return *I; + + return 0; +} + CXXMethodDecl *CXXRecordDecl::getCopyAssignmentOperator(bool ArgIsConst) const { ASTContext &Context = getASTContext(); QualType Class = Context.getTypeDeclType(const_cast<CXXRecordDecl *>(this)); @@ -387,6 +403,14 @@ CXXMethodDecl *CXXRecordDecl::getCopyAssignmentOperator(bool ArgIsConst) const { return GetBestOverloadCandidateSimple(Found); } +CXXMethodDecl *CXXRecordDecl::getMoveAssignmentOperator() const { + for (method_iterator I = method_begin(), E = method_end(); I != E; ++I) + if (I->isMoveAssignmentOperator()) + return *I; + + return 0; +} + void CXXRecordDecl::markedVirtualFunctionPure() { // C++ [class.abstract]p2: // A class is abstract if it has at least one pure virtual function. @@ -421,8 +445,10 @@ void CXXRecordDecl::addedMember(Decl *D) { // polymorphic class. data().Polymorphic = true; - // None of the special member functions are trivial. - data().HasTrivialConstructor = false; + // C++0x [class.ctor]p5 + // A default constructor is trivial [...] if: + // -- its class has no virtual functions [...] + data().HasTrivialDefaultConstructor = false; // C++0x [class.copy]p13: // A copy/move constructor for class X is trivial if [...] @@ -451,32 +477,32 @@ void CXXRecordDecl::addedMember(Decl *D) { if (ASTMutationListener *L = getASTMutationListener()) L->AddedCXXImplicitMember(data().Definition, D); + // If this is a special member function, note that it was added and then + // return early. if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { - // If this is the implicit default constructor, note that we have now - // declared it. if (Constructor->isDefaultConstructor()) data().DeclaredDefaultConstructor = true; - // If this is the implicit copy constructor, note that we have now - // declared it. else if (Constructor->isCopyConstructor()) data().DeclaredCopyConstructor = true; + else if (Constructor->isMoveConstructor()) + data().DeclaredMoveConstructor = true; + else + goto NotASpecialMember; return; - } - - if (isa<CXXDestructorDecl>(D)) { + } else if (isa<CXXDestructorDecl>(D)) { data().DeclaredDestructor = true; return; - } - - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { - // If this is the implicit copy constructor, note that we have now - // declared it. - // FIXME: Move constructors - if (Method->getOverloadedOperator() == OO_Equal) + } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { + if (Method->isCopyAssignmentOperator()) data().DeclaredCopyAssignment = true; + else if (Method->isMoveAssignmentOperator()) + data().DeclaredMoveAssignment = true; + else + goto NotASpecialMember; return; } +NotASpecialMember:; // Any other implicit declarations are handled like normal declarations. } @@ -485,23 +511,20 @@ void CXXRecordDecl::addedMember(Decl *D) { // Note that we have a user-declared constructor. data().UserDeclaredConstructor = true; - // Note that we have no need of an implicitly-declared default constructor. - data().DeclaredDefaultConstructor = true; - - // C++ [dcl.init.aggr]p1: - // An aggregate is an array or a class (clause 9) with no - // user-declared constructors (12.1) [...]. - data().Aggregate = false; - - // C++ [class]p4: - // A POD-struct is an aggregate class [...] - data().PlainOldData = false; - - // C++ [class.ctor]p5: - // A constructor is trivial if it is an implicitly-declared default - // constructor. - // FIXME: C++0x: don't do this for "= default" default constructors. - data().HasTrivialConstructor = false; + // FIXME: Under C++0x, /only/ special member functions may be user-provided. + // This is probably a defect. + bool UserProvided = false; + + // C++0x [class.ctor]p5: + // A default constructor is trivial if it is not user-provided [...] + if (Constructor->isDefaultConstructor()) { + data().DeclaredDefaultConstructor = true; + if (Constructor->isUserProvided()) { + data().HasTrivialDefaultConstructor = false; + data().UserProvidedDefaultConstructor = true; + UserProvided = true; + } + } // Note when we have a user-declared copy or move constructor, which will // suppress the implicit declaration of those constructors. @@ -511,16 +534,23 @@ void CXXRecordDecl::addedMember(Decl *D) { data().DeclaredCopyConstructor = true; // C++0x [class.copy]p13: - // A copy/move constructor for class X is trivial if it is neither - // user-provided nor deleted - // FIXME: C++0x: don't do this for "= default" copy constructors. - data().HasTrivialCopyConstructor = false; + // A copy/move constructor for class X is trivial if it is not + // user-provided [...] + if (Constructor->isUserProvided()) { + data().HasTrivialCopyConstructor = false; + UserProvided = true; + } } else if (Constructor->isMoveConstructor()) { + data().UserDeclaredMoveConstructor = true; + data().DeclaredMoveConstructor = true; + // C++0x [class.copy]p13: - // A copy/move constructor for class X is trivial if it is neither - // user-provided nor deleted - // FIXME: C++0x: don't do this for "= default" move constructors. - data().HasTrivialMoveConstructor = false; + // A copy/move constructor for class X is trivial if it is not + // user-provided [...] + if (Constructor->isUserProvided()) { + data().HasTrivialMoveConstructor = false; + UserProvided = true; + } } } if (Constructor->isConstExpr() && @@ -530,88 +560,81 @@ void CXXRecordDecl::addedMember(Decl *D) { data().HasConstExprNonCopyMoveConstructor = true; } + // C++ [dcl.init.aggr]p1: + // An aggregate is an array or a class with no user-declared + // constructors [...]. + // C++0x [dcl.init.aggr]p1: + // An aggregate is an array or a class with no user-provided + // constructors [...]. + if (!getASTContext().getLangOptions().CPlusPlus0x || UserProvided) + data().Aggregate = false; + + // C++ [class]p4: + // A POD-struct is an aggregate class [...] + // Since the POD bit is meant to be C++03 POD-ness, clear it even if the + // type is technically an aggregate in C++0x since it wouldn't be in 03. + data().PlainOldData = false; + return; } // Handle (user-declared) destructors. - if (isa<CXXDestructorDecl>(D)) { + if (CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D)) { data().DeclaredDestructor = true; data().UserDeclaredDestructor = true; // C++ [class]p4: // A POD-struct is an aggregate class that has [...] no user-defined // destructor. + // This bit is the C++03 POD bit, not the 0x one. 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; + // C++0x [class.dtor]p5: + // A destructor is trivial if it is not user-provided and [...] + if (DD->isUserProvided()) + data().HasTrivialDestructor = false; return; } // Handle (user-declared) member functions. if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { - if (Method->getOverloadedOperator() == OO_Equal) { - // We're interested specifically in copy assignment operators. - const FunctionProtoType *FnType - = Method->getType()->getAs<FunctionProtoType>(); - assert(FnType && "Overloaded operator has no proto function type."); - assert(FnType->getNumArgs() == 1 && !FnType->isVariadic()); - - // Copy assignment operators must be non-templates. - if (Method->getPrimaryTemplate() || FunTmpl) - return; - - ASTContext &Context = getASTContext(); - QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType( - const_cast<CXXRecordDecl*>(this))); - - bool isRValueRefArg = false; - QualType ArgType = FnType->getArgType(0); - if (const LValueReferenceType *Ref = - ArgType->getAs<LValueReferenceType>()) { - ArgType = Ref->getPointeeType(); - } else if (const RValueReferenceType *Ref = - ArgType->getAs<RValueReferenceType>()) { - ArgType = Ref->getPointeeType(); - isRValueRefArg = true; - } - if (!Context.hasSameUnqualifiedType(ClassType, ArgType)) - return; - + if (Method->isCopyAssignmentOperator()) { // C++ [class]p4: // A POD-struct is an aggregate class that [...] has no user-defined // copy assignment operator [...]. - // FIXME: This should be probably determined dynamically in terms of - // other more precise attributes to correctly model how it is specified - // in C++0x. Setting it here happens to do the right thing. + // This is the C++03 bit only. data().PlainOldData = false; - if (!isRValueRefArg) { - // This is a copy assignment operator. + // This is a copy assignment operator. - // Suppress the implicit declaration of a copy constructor. - data().UserDeclaredCopyAssignment = true; - data().DeclaredCopyAssignment = true; + // Suppress the implicit declaration of a copy constructor. + data().UserDeclaredCopyAssignment = true; + data().DeclaredCopyAssignment = true; - // C++0x [class.copy]p27: - // A copy/move assignment operator for class X is trivial if it is - // neither user-provided nor deleted [...] - // FIXME: C++0x: don't do this for "= default" copy operators. + // C++0x [class.copy]p27: + // A copy/move assignment operator for class X is trivial if it is + // neither user-provided nor deleted [...] + if (Method->isUserProvided()) data().HasTrivialCopyAssignment = false; - } else { - // This is a move assignment operator. - // C++0x [class.copy]p27: - // A copy/move assignment operator for class X is trivial if it is - // neither user-provided nor deleted [...] - // FIXME: C++0x: don't do this for "= default" copy operators. + return; + } + + if (Method->isMoveAssignmentOperator()) { + // This is an extension in C++03 mode, but we'll keep consistency by + // taking a move assignment operator to induce non-POD-ness + data().PlainOldData = false; + + // This is a move assignment operator. + data().UserDeclaredMoveAssignment = true; + data().DeclaredMoveAssignment = true; + + // C++0x [class.copy]p27: + // A copy/move assignment operator for class X is trivial if it is + // neither user-provided nor deleted [...] + if (Method->isUserProvided()) data().HasTrivialMoveAssignment = false; - } } // Keep the list of conversion functions up-to-date. @@ -667,6 +690,10 @@ void CXXRecordDecl::addedMember(Decl *D) { data().HasPublicFields) > 1) data().IsStandardLayout = false; + // Keep track of the presence of mutable fields. + if (Field->isMutable()) + data().HasMutableFields = true; + // C++0x [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 @@ -676,7 +703,7 @@ void CXXRecordDecl::addedMember(Decl *D) { if (!T->isPODType()) data().PlainOldData = false; if (T->isReferenceType()) { - data().HasTrivialConstructor = false; + data().HasTrivialDefaultConstructor = false; // C++0x [class]p7: // A standard-layout class is a class that: @@ -688,11 +715,32 @@ void CXXRecordDecl::addedMember(Decl *D) { if (!hasNonLiteralTypeFieldsOrBases() && !T->isLiteralType()) data().HasNonLiteralTypeFieldsOrBases = true; + if (Field->hasInClassInitializer()) { + // C++0x [class]p5: + // A default constructor is trivial if [...] no non-static data member + // of its class has a brace-or-equal-initializer. + data().HasTrivialDefaultConstructor = false; + + // C++0x [dcl.init.aggr]p1: + // An aggregate is a [...] class with [...] no + // brace-or-equal-initializers for non-static data members. + data().Aggregate = false; + + // C++0x [class]p10: + // A POD struct is [...] a trivial class. + data().PlainOldData = false; + } + if (const RecordType *RecordTy = T->getAs<RecordType>()) { CXXRecordDecl* FieldRec = cast<CXXRecordDecl>(RecordTy->getDecl()); if (FieldRec->getDefinition()) { - if (!FieldRec->hasTrivialConstructor()) - data().HasTrivialConstructor = false; + // C++0x [class.ctor]p5: + // A defulat constructor is trivial [...] if: + // -- for all the non-static data members of its class that are of + // class type (or array thereof), each such class has a trivial + // default constructor. + if (!FieldRec->hasTrivialDefaultConstructor()) + data().HasTrivialDefaultConstructor = false; // C++0x [class.copy]p13: // A copy/move constructor for class X is trivial if [...] @@ -753,6 +801,10 @@ void CXXRecordDecl::addedMember(Decl *D) { } } } + + // Keep track of the presence of mutable fields. + if (FieldRec->hasMutableFields()) + data().HasMutableFields = true; } } @@ -1135,14 +1187,13 @@ bool CXXMethodDecl::isUsualDeallocationFunction() const { } bool CXXMethodDecl::isCopyAssignmentOperator() const { - // C++0x [class.copy]p19: + // C++0x [class.copy]p17: // A user-declared copy assignment operator X::operator= is a non-static // non-template member function of class X with exactly one parameter of // type X, X&, const X&, volatile X& or const volatile X&. if (/*operator=*/getOverloadedOperator() != OO_Equal || /*non-static*/ isStatic() || - /*non-template*/getPrimaryTemplate() || getDescribedFunctionTemplate() || - /*exactly one parameter*/getNumParams() != 1) + /*non-template*/getPrimaryTemplate() || getDescribedFunctionTemplate()) return false; QualType ParamType = getParamDecl(0)->getType(); @@ -1155,6 +1206,26 @@ bool CXXMethodDecl::isCopyAssignmentOperator() const { return Context.hasSameUnqualifiedType(ClassType, ParamType); } +bool CXXMethodDecl::isMoveAssignmentOperator() const { + // C++0x [class.copy]p19: + // A user-declared move assignment operator X::operator= is a non-static + // non-template member function of class X with exactly one parameter of type + // X&&, const X&&, volatile X&&, or const volatile X&&. + if (getOverloadedOperator() != OO_Equal || isStatic() || + getPrimaryTemplate() || getDescribedFunctionTemplate()) + return false; + + QualType ParamType = getParamDecl(0)->getType(); + if (!isa<RValueReferenceType>(ParamType)) + return false; + ParamType = ParamType->getPointeeType(); + + ASTContext &Context = getASTContext(); + QualType ClassType + = Context.getCanonicalType(Context.getTypeDeclType(getParent())); + return Context.hasSameUnqualifiedType(ClassType, ParamType); +} + void CXXMethodDecl::addOverriddenMethod(const CXXMethodDecl *MD) { assert(MD->isCanonicalDecl() && "Method is not canonical!"); assert(!MD->getParent()->isDependentContext() && @@ -1290,11 +1361,21 @@ const Type *CXXCtorInitializer::getBaseClass() const { SourceLocation CXXCtorInitializer::getSourceLocation() const { if (isAnyMemberInitializer() || isDelegatingInitializer()) return getMemberLocation(); + + if (isInClassMemberInitializer()) + return getAnyMember()->getLocation(); return getBaseClassLoc().getLocalSourceRange().getBegin(); } SourceRange CXXCtorInitializer::getSourceRange() const { + if (isInClassMemberInitializer()) { + FieldDecl *D = getAnyMember(); + if (Expr *I = D->getInClassInitializer()) + return I->getSourceRange(); + return SourceRange(); + } + return SourceRange(getSourceLocation(), getRParenLoc()); } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp index 24d281e..e2c4f38 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp @@ -339,12 +339,14 @@ ObjCMethodDecl *ObjCMethodDecl::Create(ASTContext &C, bool isSynthesized, bool isDefined, ImplementationControl impControl, + bool HasRelatedResultType, unsigned numSelectorArgs) { return new (C) ObjCMethodDecl(beginLoc, endLoc, SelInfo, T, ResultTInfo, contextDecl, isInstance, isVariadic, isSynthesized, isDefined, impControl, + HasRelatedResultType, numSelectorArgs); } @@ -446,6 +448,7 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const { case OMF_release: case OMF_autorelease: case OMF_retainCount: + case OMF_self: if (!isInstanceMethod()) family = OMF_None; break; diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp index 2fd88d7..421770e 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp @@ -400,7 +400,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (D->getNumParams()) POut << ", "; POut << "..."; } - } else if (D->isThisDeclarationADefinition() && !D->hasPrototype()) { + } else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) { for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { if (i) Proto += ", "; @@ -450,62 +450,67 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (D->hasAttr<NoReturnAttr>()) Proto += " __attribute((noreturn))"; if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) { - if (CDecl->getNumCtorInitializers() > 0) { - Proto += " : "; - Out << Proto; - Proto.clear(); - for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(), - E = CDecl->init_end(); - B != E; ++B) { - CXXCtorInitializer * BMInitializer = (*B); - if (B != CDecl->init_begin()) - Out << ", "; - if (BMInitializer->isAnyMemberInitializer()) { - FieldDecl *FD = BMInitializer->getAnyMember(); - Out << FD; - } else { - Out << QualType(BMInitializer->getBaseClass(), - 0).getAsString(Policy); - } + bool HasInitializerList = false; + for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(), + E = CDecl->init_end(); + B != E; ++B) { + CXXCtorInitializer * BMInitializer = (*B); + if (BMInitializer->isInClassMemberInitializer()) + continue; + + if (!HasInitializerList) { + Proto += " : "; + Out << Proto; + Proto.clear(); + HasInitializerList = true; + } else + Out << ", "; + + if (BMInitializer->isAnyMemberInitializer()) { + FieldDecl *FD = BMInitializer->getAnyMember(); + Out << FD; + } else { + Out << QualType(BMInitializer->getBaseClass(), + 0).getAsString(Policy); + } + + Out << "("; + if (!BMInitializer->getInit()) { + // Nothing to print + } else { + Expr *Init = BMInitializer->getInit(); + if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init)) + Init = Tmp->getSubExpr(); + + Init = Init->IgnoreParens(); - Out << "("; - if (!BMInitializer->getInit()) { - // Nothing to print - } else { - Expr *Init = BMInitializer->getInit(); - if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init)) - Init = Tmp->getSubExpr(); - - Init = Init->IgnoreParens(); - - Expr *SimpleInit = 0; - Expr **Args = 0; - unsigned NumArgs = 0; - if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { - Args = ParenList->getExprs(); - NumArgs = ParenList->getNumExprs(); - } else if (CXXConstructExpr *Construct - = dyn_cast<CXXConstructExpr>(Init)) { - Args = Construct->getArgs(); - NumArgs = Construct->getNumArgs(); - } else - SimpleInit = Init; - - if (SimpleInit) - SimpleInit->printPretty(Out, Context, 0, Policy, Indentation); - else { - for (unsigned I = 0; I != NumArgs; ++I) { - if (isa<CXXDefaultArgExpr>(Args[I])) - break; - - if (I) - Out << ", "; - Args[I]->printPretty(Out, Context, 0, Policy, Indentation); - } + Expr *SimpleInit = 0; + Expr **Args = 0; + unsigned NumArgs = 0; + if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { + Args = ParenList->getExprs(); + NumArgs = ParenList->getNumExprs(); + } else if (CXXConstructExpr *Construct + = dyn_cast<CXXConstructExpr>(Init)) { + Args = Construct->getArgs(); + NumArgs = Construct->getNumArgs(); + } else + SimpleInit = Init; + + if (SimpleInit) + SimpleInit->printPretty(Out, Context, 0, Policy, Indentation); + else { + for (unsigned I = 0; I != NumArgs; ++I) { + if (isa<CXXDefaultArgExpr>(Args[I])) + break; + + if (I) + Out << ", "; + Args[I]->printPretty(Out, Context, 0, Policy, Indentation); } } - Out << ")"; } + Out << ")"; } } else @@ -518,9 +523,9 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (D->isPure()) Out << " = 0"; - else if (D->isDeleted()) + else if (D->isDeletedAsWritten()) Out << " = delete"; - else if (D->isThisDeclarationADefinition()) { + else if (D->doesThisDeclarationHaveABody()) { if (!D->hasPrototype() && D->getNumParams()) { // This is a K&R function definition, so we need to print the // parameters. @@ -553,6 +558,12 @@ void DeclPrinter::VisitFieldDecl(FieldDecl *D) { Out << " : "; D->getBitWidth()->printPretty(Out, Context, 0, Policy, Indentation); } + + Expr *Init = D->getInClassInitializer(); + if (!Policy.SuppressInitializers && Init) { + Out << " = "; + Init->printPretty(Out, Context, 0, Policy, Indentation); + } } void DeclPrinter::VisitLabelDecl(LabelDecl *D) { @@ -932,6 +943,11 @@ void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) { Out << (first ? ' ' : ',') << "nonatomic"; first = false; } + if (PDecl->getPropertyAttributes() & + ObjCPropertyDecl::OBJC_PR_atomic) { + Out << (first ? ' ' : ',') << "atomic"; + first = false; + } Out << " )"; } Out << ' ' << PDecl->getType().getAsString(Policy) << ' ' << PDecl; diff --git a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp index 6272340..bc375d0a 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp @@ -735,3 +735,34 @@ FriendTemplateDecl *FriendTemplateDecl::Create(ASTContext &Context, EmptyShell Empty) { return new (Context) FriendTemplateDecl(Empty); } + +//===----------------------------------------------------------------------===// +// TypeAliasTemplateDecl Implementation +//===----------------------------------------------------------------------===// + +TypeAliasTemplateDecl *TypeAliasTemplateDecl::Create(ASTContext &C, + DeclContext *DC, + SourceLocation L, + DeclarationName Name, + TemplateParameterList *Params, + NamedDecl *Decl) { + AdoptTemplateParameterList(Params, DC); + return new (C) TypeAliasTemplateDecl(DC, L, Name, Params, Decl); +} + +TypeAliasTemplateDecl *TypeAliasTemplateDecl::Create(ASTContext &C, + EmptyShell) { + return new (C) TypeAliasTemplateDecl(0, SourceLocation(), DeclarationName(), + 0, 0); +} + +void TypeAliasTemplateDecl::DeallocateCommon(void *Ptr) { + static_cast<Common *>(Ptr)->~Common(); +} +RedeclarableTemplateDecl::CommonBase * +TypeAliasTemplateDecl::newCommon(ASTContext &C) { + Common *CommonPtr = new (C) Common; + C.AddDeallocation(DeallocateCommon, CommonPtr); + return CommonPtr; +} + diff --git a/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp b/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp index 7d593bc..dfe0119 100644 --- a/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp @@ -482,18 +482,20 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, setFlag("trivial", D->isTrivial()); setFlag("returnzero", D->hasImplicitReturnZero()); setFlag("prototype", D->hasWrittenPrototype()); - setFlag("deleted", D->isDeleted()); + setFlag("deleted", D->isDeletedAsWritten()); if (D->getStorageClass() != SC_None) set("storage", VarDecl::getStorageClassSpecifierString(D->getStorageClass())); setFlag("inline", D->isInlineSpecified()); + if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) + set("asmlabel", ALA->getLabel()); // TODO: instantiation, etc. } void visitFunctionDeclChildren(FunctionDecl *D) { for (FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end(); I != E; ++I) dispatch(*I); - if (D->isThisDeclarationADefinition()) + if (D->doesThisDeclarationHaveABody()) dispatch(D->getBody()); } @@ -619,7 +621,8 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, // TemplateDecl void visitTemplateDeclChildren(TemplateDecl *D) { visitTemplateParameters(D->getTemplateParameters()); - dispatch(D->getTemplatedDecl()); + if (D->getTemplatedDecl()) + dispatch(D->getTemplatedDecl()); } // FunctionTemplateDecl @@ -845,6 +848,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, setFlag("variadic", D->isVariadic()); setFlag("synthesized", D->isSynthesized()); setFlag("defined", D->isDefined()); + setFlag("related_result_type", D->hasRelatedResultType()); } void visitObjCMethodDeclChildren(ObjCMethodDecl *D) { dispatch(D->getResultType()); diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp index 6499f32..9872139 100644 --- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp @@ -22,6 +22,7 @@ #include "clang/AST/StmtVisitor.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Lex/Lexer.h" +#include "clang/Sema/SemaDiagnostic.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -1653,7 +1654,8 @@ static Expr::CanThrowResult CanSubExprsThrow(ASTContext &C, const Expr *CE) { return R; } -static Expr::CanThrowResult CanCalleeThrow(ASTContext &Ctx, const Decl *D, +static Expr::CanThrowResult CanCalleeThrow(ASTContext &Ctx, const Expr *E, + const Decl *D, bool NullThrows = true) { if (!D) return NullThrows ? Expr::CT_Can : Expr::CT_Cannot; @@ -1683,6 +1685,15 @@ static Expr::CanThrowResult CanCalleeThrow(ASTContext &Ctx, const Decl *D, if (!FT) return Expr::CT_Can; + if (FT->getExceptionSpecType() == EST_Delayed) { + assert(isa<CXXConstructorDecl>(D) && + "only constructor exception specs can be unknown"); + Ctx.getDiagnostics().Report(E->getLocStart(), + diag::err_exception_spec_unknown) + << E->getSourceRange(); + return Expr::CT_Can; + } + return FT->isNothrow(Ctx) ? Expr::CT_Cannot : Expr::CT_Can; } @@ -1693,6 +1704,9 @@ static Expr::CanThrowResult CanDynamicCastThrow(const CXXDynamicCastExpr *DC) { if (!DC->getTypeAsWritten()->isReferenceType()) return Expr::CT_Cannot; + if (DC->getSubExpr()->isTypeDependent()) + return Expr::CT_Dependent; + return DC->getCastKind() == clang::CK_Dynamic? Expr::CT_Can : Expr::CT_Cannot; } @@ -1747,7 +1761,14 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { case CallExprClass: case CXXOperatorCallExprClass: case CXXMemberCallExprClass: { - CanThrowResult CT = CanCalleeThrow(C,cast<CallExpr>(this)->getCalleeDecl()); + const CallExpr *CE = cast<CallExpr>(this); + CanThrowResult CT; + if (isTypeDependent()) + CT = CT_Dependent; + else if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens())) + CT = CT_Cannot; + else + CT = CanCalleeThrow(C, this, CE->getCalleeDecl()); if (CT == CT_Can) return CT; return MergeCanThrow(CT, CanSubExprsThrow(C, this)); @@ -1755,7 +1776,7 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { case CXXConstructExprClass: case CXXTemporaryObjectExprClass: { - CanThrowResult CT = CanCalleeThrow(C, + CanThrowResult CT = CanCalleeThrow(C, this, cast<CXXConstructExpr>(this)->getConstructor()); if (CT == CT_Can) return CT; @@ -1763,9 +1784,13 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { } case CXXNewExprClass: { - CanThrowResult CT = MergeCanThrow( - CanCalleeThrow(C, cast<CXXNewExpr>(this)->getOperatorNew()), - CanCalleeThrow(C, cast<CXXNewExpr>(this)->getConstructor(), + CanThrowResult CT; + if (isTypeDependent()) + CT = CT_Dependent; + else + CT = MergeCanThrow( + CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getOperatorNew()), + CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getConstructor(), /*NullThrows*/false)); if (CT == CT_Can) return CT; @@ -1773,29 +1798,26 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { } case CXXDeleteExprClass: { - CanThrowResult CT = CanCalleeThrow(C, - cast<CXXDeleteExpr>(this)->getOperatorDelete()); - if (CT == CT_Can) - return CT; - const Expr *Arg = cast<CXXDeleteExpr>(this)->getArgument(); - // Unwrap exactly one implicit cast, which converts all pointers to void*. - if (const ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg)) - Arg = Cast->getSubExpr(); - if (const PointerType *PT = Arg->getType()->getAs<PointerType>()) { - if (const RecordType *RT = PT->getPointeeType()->getAs<RecordType>()) { - CanThrowResult CT2 = CanCalleeThrow(C, - cast<CXXRecordDecl>(RT->getDecl())->getDestructor()); - if (CT2 == CT_Can) - return CT2; - CT = MergeCanThrow(CT, CT2); + CanThrowResult CT; + QualType DTy = cast<CXXDeleteExpr>(this)->getDestroyedType(); + if (DTy.isNull() || DTy->isDependentType()) { + CT = CT_Dependent; + } else { + CT = CanCalleeThrow(C, this, + cast<CXXDeleteExpr>(this)->getOperatorDelete()); + if (const RecordType *RT = DTy->getAs<RecordType>()) { + const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + CT = MergeCanThrow(CT, CanCalleeThrow(C, this, RD->getDestructor())); } + if (CT == CT_Can) + return CT; } return MergeCanThrow(CT, CanSubExprsThrow(C, this)); } case CXXBindTemporaryExprClass: { // The bound temporary has to be destroyed again, which might throw. - CanThrowResult CT = CanCalleeThrow(C, + CanThrowResult CT = CanCalleeThrow(C, this, cast<CXXBindTemporaryExpr>(this)->getTemporary()->getDestructor()); if (CT == CT_Can) return CT; @@ -1978,6 +2000,14 @@ Expr *Expr::IgnoreParenImpCasts() { } } +Expr *Expr::IgnoreConversionOperator() { + if (CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(this)) { + if (isa<CXXConversionDecl>(MCE->getMethodDecl())) + return MCE->getImplicitObjectArgument(); + } + return this; +} + /// IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the /// value (including ptr->int casts of the same size). Strip off any /// ParenExpr or CastExprs, returning their operand. @@ -3013,4 +3043,3 @@ BlockDeclRefExpr::BlockDeclRefExpr(VarDecl *d, QualType t, ExprValueKind VK, ExprBits.TypeDependent = TypeDependent; ExprBits.ValueDependent = ValueDependent; } - diff --git a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp index 888a93c..d177cb5 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp @@ -161,6 +161,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::InitListExprClass: case Expr::SizeOfPackExprClass: case Expr::SubstNonTypeTemplateParmPackExprClass: + case Expr::AsTypeExprClass: return Cl::CL_PRValue; // Next come the complicated cases. @@ -465,14 +466,16 @@ static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) { // is a pointer to a data member is of the same value category as its first // operand. if (E->getOpcode() == BO_PtrMemD) - return E->getType()->isFunctionType() ? Cl::CL_MemberFunction : - ClassifyInternal(Ctx, E->getLHS()); + return (E->getType()->isFunctionType() || E->getType() == Ctx.BoundMemberTy) + ? Cl::CL_MemberFunction + : ClassifyInternal(Ctx, E->getLHS()); // C++ [expr.mptr.oper]p6: The result of an ->* expression is an lvalue if its // second operand is a pointer to data member and a prvalue otherwise. if (E->getOpcode() == BO_PtrMemI) - return E->getType()->isFunctionType() ? - Cl::CL_MemberFunction : Cl::CL_LValue; + return (E->getType()->isFunctionType() || E->getType() == Ctx.BoundMemberTy) + ? Cl::CL_MemberFunction + : Cl::CL_LValue; // All other binary operations are prvalues. return Cl::CL_PRValue; diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp index c2caf8d4..06c5645 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp @@ -102,10 +102,10 @@ namespace { }; struct LValue { - Expr *Base; + const Expr *Base; CharUnits Offset; - Expr *getLValueBase() { return Base; } + const Expr *getLValueBase() { return Base; } CharUnits getLValueOffset() { return Offset; } void moveInto(APValue &v) const { @@ -221,7 +221,7 @@ static APSInt HandleFloatToIntCast(QualType DestType, QualType SrcType, APFloat &Value, const ASTContext &Ctx) { unsigned DestWidth = Ctx.getIntWidth(DestType); // Determine whether we are converting to unsigned or signed. - bool DestSigned = DestType->isSignedIntegerType(); + bool DestSigned = DestType->isSignedIntegerOrEnumerationType(); // FIXME: Warning for overflow. uint64_t Space[4]; @@ -247,7 +247,7 @@ static APSInt HandleIntToIntCast(QualType DestType, QualType SrcType, // Figure out if this is a truncate, extend or noop cast. // If the input is signed, do a sign extend, noop, or truncate. Result = Result.extOrTrunc(DestWidth); - Result.setIsUnsigned(DestType->isUnsignedIntegerType()); + Result.setIsUnsigned(DestType->isUnsignedIntegerOrEnumerationType()); return Result; } @@ -262,69 +262,69 @@ static APFloat HandleIntToFloatCast(QualType DestType, QualType SrcType, namespace { class HasSideEffect - : public StmtVisitor<HasSideEffect, bool> { + : public ConstStmtVisitor<HasSideEffect, bool> { EvalInfo &Info; public: HasSideEffect(EvalInfo &info) : Info(info) {} // Unhandled nodes conservatively default to having side effects. - bool VisitStmt(Stmt *S) { + bool VisitStmt(const Stmt *S) { return true; } - bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } - bool VisitGenericSelectionExpr(GenericSelectionExpr *E) { + bool VisitParenExpr(const ParenExpr *E) { return Visit(E->getSubExpr()); } + bool VisitGenericSelectionExpr(const GenericSelectionExpr *E) { return Visit(E->getResultExpr()); } - bool VisitDeclRefExpr(DeclRefExpr *E) { + bool VisitDeclRefExpr(const DeclRefExpr *E) { if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified()) return true; return false; } // We don't want to evaluate BlockExprs multiple times, as they generate // a ton of code. - bool VisitBlockExpr(BlockExpr *E) { return true; } - bool VisitPredefinedExpr(PredefinedExpr *E) { return false; } - bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E) + bool VisitBlockExpr(const BlockExpr *E) { return true; } + bool VisitPredefinedExpr(const PredefinedExpr *E) { return false; } + bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { return Visit(E->getInitializer()); } - bool VisitMemberExpr(MemberExpr *E) { return Visit(E->getBase()); } - bool VisitIntegerLiteral(IntegerLiteral *E) { return false; } - bool VisitFloatingLiteral(FloatingLiteral *E) { return false; } - bool VisitStringLiteral(StringLiteral *E) { return false; } - bool VisitCharacterLiteral(CharacterLiteral *E) { return false; } - bool VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) + bool VisitMemberExpr(const MemberExpr *E) { return Visit(E->getBase()); } + bool VisitIntegerLiteral(const IntegerLiteral *E) { return false; } + bool VisitFloatingLiteral(const FloatingLiteral *E) { return false; } + bool VisitStringLiteral(const StringLiteral *E) { return false; } + bool VisitCharacterLiteral(const CharacterLiteral *E) { return false; } + bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E) { return false; } - bool VisitArraySubscriptExpr(ArraySubscriptExpr *E) + bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { return Visit(E->getLHS()) || Visit(E->getRHS()); } - bool VisitChooseExpr(ChooseExpr *E) + bool VisitChooseExpr(const ChooseExpr *E) { return Visit(E->getChosenSubExpr(Info.Ctx)); } - bool VisitCastExpr(CastExpr *E) { return Visit(E->getSubExpr()); } - bool VisitBinAssign(BinaryOperator *E) { return true; } - bool VisitCompoundAssignOperator(BinaryOperator *E) { return true; } - bool VisitBinaryOperator(BinaryOperator *E) + bool VisitCastExpr(const CastExpr *E) { return Visit(E->getSubExpr()); } + bool VisitBinAssign(const BinaryOperator *E) { return true; } + bool VisitCompoundAssignOperator(const BinaryOperator *E) { return true; } + bool VisitBinaryOperator(const BinaryOperator *E) { return Visit(E->getLHS()) || Visit(E->getRHS()); } - bool VisitUnaryPreInc(UnaryOperator *E) { return true; } - bool VisitUnaryPostInc(UnaryOperator *E) { return true; } - bool VisitUnaryPreDec(UnaryOperator *E) { return true; } - bool VisitUnaryPostDec(UnaryOperator *E) { return true; } - bool VisitUnaryDeref(UnaryOperator *E) { + bool VisitUnaryPreInc(const UnaryOperator *E) { return true; } + bool VisitUnaryPostInc(const UnaryOperator *E) { return true; } + bool VisitUnaryPreDec(const UnaryOperator *E) { return true; } + bool VisitUnaryPostDec(const UnaryOperator *E) { return true; } + bool VisitUnaryDeref(const UnaryOperator *E) { if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified()) return true; return Visit(E->getSubExpr()); } - bool VisitUnaryOperator(UnaryOperator *E) { return Visit(E->getSubExpr()); } + bool VisitUnaryOperator(const UnaryOperator *E) { return Visit(E->getSubExpr()); } // Has side effects if any element does. - bool VisitInitListExpr(InitListExpr *E) { + bool VisitInitListExpr(const InitListExpr *E) { for (unsigned i = 0, e = E->getNumInits(); i != e; ++i) if (Visit(E->getInit(i))) return true; - if (Expr *filler = E->getArrayFiller()) + if (const Expr *filler = E->getArrayFiller()) return Visit(filler); return false; } - bool VisitSizeOfPackExpr(SizeOfPackExpr *) { return false; } + bool VisitSizeOfPackExpr(const SizeOfPackExpr *) { return false; } }; class OpaqueValueEvaluation { @@ -354,15 +354,89 @@ public: } // end anonymous namespace //===----------------------------------------------------------------------===// +// Generic Evaluation +//===----------------------------------------------------------------------===// +namespace { + +template <class Derived, typename RetTy=void> +class ExprEvaluatorBase + : public ConstStmtVisitor<Derived, RetTy> { +private: + RetTy DerivedSuccess(const APValue &V, const Expr *E) { + return static_cast<Derived*>(this)->Success(V, E); + } + RetTy DerivedError(const Expr *E) { + return static_cast<Derived*>(this)->Error(E); + } + +protected: + EvalInfo &Info; + typedef ConstStmtVisitor<Derived, RetTy> StmtVisitorTy; + typedef ExprEvaluatorBase ExprEvaluatorBaseTy; + +public: + ExprEvaluatorBase(EvalInfo &Info) : Info(Info) {} + + RetTy VisitStmt(const Stmt *) { + assert(0 && "Expression evaluator should not be called on stmts"); + return DerivedError(0); + } + RetTy VisitExpr(const Expr *E) { + return DerivedError(E); + } + + RetTy VisitParenExpr(const ParenExpr *E) + { return StmtVisitorTy::Visit(E->getSubExpr()); } + RetTy VisitUnaryExtension(const UnaryOperator *E) + { return StmtVisitorTy::Visit(E->getSubExpr()); } + RetTy VisitUnaryPlus(const UnaryOperator *E) + { return StmtVisitorTy::Visit(E->getSubExpr()); } + RetTy VisitChooseExpr(const ChooseExpr *E) + { return StmtVisitorTy::Visit(E->getChosenSubExpr(Info.Ctx)); } + RetTy VisitGenericSelectionExpr(const GenericSelectionExpr *E) + { return StmtVisitorTy::Visit(E->getResultExpr()); } + + RetTy VisitBinaryConditionalOperator(const BinaryConditionalOperator *E) { + OpaqueValueEvaluation opaque(Info, E->getOpaqueValue(), E->getCommon()); + if (opaque.hasError()) + return DerivedError(E); + + bool cond; + if (!HandleConversionToBool(E->getCond(), cond, Info)) + return DerivedError(E); + + return StmtVisitorTy::Visit(cond ? E->getTrueExpr() : E->getFalseExpr()); + } + + RetTy VisitConditionalOperator(const ConditionalOperator *E) { + bool BoolResult; + if (!HandleConversionToBool(E->getCond(), BoolResult, Info)) + return DerivedError(E); + + Expr* EvalExpr = BoolResult ? E->getTrueExpr() : E->getFalseExpr(); + return StmtVisitorTy::Visit(EvalExpr); + } + + RetTy VisitOpaqueValueExpr(const OpaqueValueExpr *E) { + const APValue *value = Info.getOpaqueValue(E); + if (!value) + return (E->getSourceExpr() ? StmtVisitorTy::Visit(E->getSourceExpr()) + : DerivedError(E)); + return DerivedSuccess(*value, E); + } +}; + +} + +//===----------------------------------------------------------------------===// // LValue Evaluation //===----------------------------------------------------------------------===// namespace { class LValueExprEvaluator - : public StmtVisitor<LValueExprEvaluator, bool> { - EvalInfo &Info; + : public ExprEvaluatorBase<LValueExprEvaluator, bool> { LValue &Result; - bool Success(Expr *E) { + bool Success(const Expr *E) { Result.Base = E; Result.Offset = CharUnits::Zero(); return true; @@ -370,30 +444,26 @@ class LValueExprEvaluator public: LValueExprEvaluator(EvalInfo &info, LValue &Result) : - Info(info), Result(Result) {} + ExprEvaluatorBaseTy(info), Result(Result) {} - bool VisitStmt(Stmt *S) { + bool Success(const APValue &V, const Expr *E) { + Result.setFrom(V); + return true; + } + bool Error(const Expr *E) { return false; } - bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } - bool VisitGenericSelectionExpr(GenericSelectionExpr *E) { - return Visit(E->getResultExpr()); - } - bool VisitDeclRefExpr(DeclRefExpr *E); - bool VisitPredefinedExpr(PredefinedExpr *E) { return Success(E); } - bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E); - bool VisitMemberExpr(MemberExpr *E); - bool VisitStringLiteral(StringLiteral *E) { return Success(E); } - bool VisitObjCEncodeExpr(ObjCEncodeExpr *E) { return Success(E); } - bool VisitArraySubscriptExpr(ArraySubscriptExpr *E); - bool VisitUnaryDeref(UnaryOperator *E); - bool VisitUnaryExtension(const UnaryOperator *E) - { return Visit(E->getSubExpr()); } - bool VisitChooseExpr(const ChooseExpr *E) - { return Visit(E->getChosenSubExpr(Info.Ctx)); } - - bool VisitCastExpr(CastExpr *E) { + bool VisitDeclRefExpr(const DeclRefExpr *E); + bool VisitPredefinedExpr(const PredefinedExpr *E) { return Success(E); } + bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E); + bool VisitMemberExpr(const MemberExpr *E); + bool VisitStringLiteral(const StringLiteral *E) { return Success(E); } + bool VisitObjCEncodeExpr(const ObjCEncodeExpr *E) { return Success(E); } + bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E); + bool VisitUnaryDeref(const UnaryOperator *E); + + bool VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: return false; @@ -403,36 +473,37 @@ public: } } // FIXME: Missing: __real__, __imag__ + }; } // end anonymous namespace static bool EvaluateLValue(const Expr* E, LValue& Result, EvalInfo &Info) { - return LValueExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E)); + return LValueExprEvaluator(Info, Result).Visit(E); } -bool LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E) { +bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { if (isa<FunctionDecl>(E->getDecl())) { return Success(E); - } else if (VarDecl* VD = dyn_cast<VarDecl>(E->getDecl())) { + } else if (const VarDecl* VD = dyn_cast<VarDecl>(E->getDecl())) { if (!VD->getType()->isReferenceType()) return Success(E); // Reference parameters can refer to anything even if they have an // "initializer" in the form of a default argument. - if (isa<ParmVarDecl>(VD)) - return false; - // FIXME: Check whether VD might be overridden! - if (const Expr *Init = VD->getAnyInitializer()) - return Visit(const_cast<Expr *>(Init)); + if (!isa<ParmVarDecl>(VD)) + // FIXME: Check whether VD might be overridden! + if (const Expr *Init = VD->getAnyInitializer()) + return Visit(Init); } - return false; + return ExprEvaluatorBaseTy::VisitDeclRefExpr(E); } -bool LValueExprEvaluator::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { +bool +LValueExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { return Success(E); } -bool LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) { +bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) { QualType Ty; if (E->isArrow()) { if (!EvaluatePointer(E->getBase(), Result, Info)) @@ -444,10 +515,10 @@ bool LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) { Ty = E->getBase()->getType(); } - RecordDecl *RD = Ty->getAs<RecordType>()->getDecl(); + const RecordDecl *RD = Ty->getAs<RecordType>()->getDecl(); const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD); - FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl()); + const FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl()); if (!FD) // FIXME: deal with other kinds of member expressions return false; @@ -467,7 +538,7 @@ bool LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) { return true; } -bool LValueExprEvaluator::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { +bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { if (!EvaluatePointer(E->getBase(), Result, Info)) return false; @@ -480,7 +551,7 @@ bool LValueExprEvaluator::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { return true; } -bool LValueExprEvaluator::VisitUnaryDeref(UnaryOperator *E) { +bool LValueExprEvaluator::VisitUnaryDeref(const UnaryOperator *E) { return EvaluatePointer(E->getSubExpr(), Result, Info); } @@ -490,11 +561,10 @@ bool LValueExprEvaluator::VisitUnaryDeref(UnaryOperator *E) { namespace { class PointerExprEvaluator - : public StmtVisitor<PointerExprEvaluator, bool> { - EvalInfo &Info; + : public ExprEvaluatorBase<PointerExprEvaluator, bool> { LValue &Result; - bool Success(Expr *E) { + bool Success(const Expr *E) { Result.Base = E; Result.Offset = CharUnits::Zero(); return true; @@ -502,49 +572,41 @@ class PointerExprEvaluator public: PointerExprEvaluator(EvalInfo &info, LValue &Result) - : Info(info), Result(Result) {} + : ExprEvaluatorBaseTy(info), Result(Result) {} - bool VisitStmt(Stmt *S) { - return false; + bool Success(const APValue &V, const Expr *E) { + Result.setFrom(V); + return true; } - - bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } - bool VisitGenericSelectionExpr(GenericSelectionExpr *E) { - return Visit(E->getResultExpr()); + bool Error(const Stmt *S) { + return false; } bool VisitBinaryOperator(const BinaryOperator *E); - bool VisitCastExpr(CastExpr* E); - bool VisitUnaryExtension(const UnaryOperator *E) - { return Visit(E->getSubExpr()); } + bool VisitCastExpr(const CastExpr* E); bool VisitUnaryAddrOf(const UnaryOperator *E); - bool VisitObjCStringLiteral(ObjCStringLiteral *E) + bool VisitObjCStringLiteral(const ObjCStringLiteral *E) { return Success(E); } - bool VisitAddrLabelExpr(AddrLabelExpr *E) + bool VisitAddrLabelExpr(const AddrLabelExpr *E) { return Success(E); } - bool VisitCallExpr(CallExpr *E); - bool VisitBlockExpr(BlockExpr *E) { + bool VisitCallExpr(const CallExpr *E); + bool VisitBlockExpr(const BlockExpr *E) { if (!E->getBlockDecl()->hasCaptures()) return Success(E); return false; } - bool VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) + bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { return Success((Expr*)0); } - bool VisitBinaryConditionalOperator(BinaryConditionalOperator *E); - bool VisitConditionalOperator(ConditionalOperator *E); - bool VisitChooseExpr(ChooseExpr *E) - { return Visit(E->getChosenSubExpr(Info.Ctx)); } - bool VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) + bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) { return Success((Expr*)0); } - bool VisitOpaqueValueExpr(OpaqueValueExpr *E); // FIXME: Missing: @protocol, @selector }; } // end anonymous namespace static bool EvaluatePointer(const Expr* E, LValue& Result, EvalInfo &Info) { assert(E->getType()->hasPointerRepresentation()); - return PointerExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E)); + return PointerExprEvaluator(Info, Result).Visit(E); } bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { @@ -592,8 +654,8 @@ bool PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) { } -bool PointerExprEvaluator::VisitCastExpr(CastExpr* E) { - Expr* SubExpr = E->getSubExpr(); +bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { + const Expr* SubExpr = E->getSubExpr(); switch (E->getCastKind()) { default: @@ -671,42 +733,14 @@ bool PointerExprEvaluator::VisitCastExpr(CastExpr* E) { return false; } -bool PointerExprEvaluator::VisitCallExpr(CallExpr *E) { +bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) { if (E->isBuiltinCall(Info.Ctx) == Builtin::BI__builtin___CFStringMakeConstantString || E->isBuiltinCall(Info.Ctx) == Builtin::BI__builtin___NSStringMakeConstantString) return Success(E); - return false; -} - -bool PointerExprEvaluator::VisitOpaqueValueExpr(OpaqueValueExpr *e) { - const APValue *value = Info.getOpaqueValue(e); - if (!value) - return (e->getSourceExpr() ? Visit(e->getSourceExpr()) : false); - Result.setFrom(*value); - return true; -} - -bool PointerExprEvaluator:: -VisitBinaryConditionalOperator(BinaryConditionalOperator *e) { - OpaqueValueEvaluation opaque(Info, e->getOpaqueValue(), e->getCommon()); - if (opaque.hasError()) return false; - bool cond; - if (!HandleConversionToBool(e->getCond(), cond, Info)) - return false; - - return Visit(cond ? e->getTrueExpr() : e->getFalseExpr()); -} - -bool PointerExprEvaluator::VisitConditionalOperator(ConditionalOperator *E) { - bool BoolResult; - if (!HandleConversionToBool(E->getCond(), BoolResult, Info)) - return false; - - Expr* EvalExpr = BoolResult ? E->getTrueExpr() : E->getFalseExpr(); - return Visit(EvalExpr); + return ExprEvaluatorBaseTy::VisitCallExpr(E); } //===----------------------------------------------------------------------===// @@ -715,25 +749,15 @@ bool PointerExprEvaluator::VisitConditionalOperator(ConditionalOperator *E) { namespace { class VectorExprEvaluator - : public StmtVisitor<VectorExprEvaluator, APValue> { - EvalInfo &Info; + : public ExprEvaluatorBase<VectorExprEvaluator, APValue> { APValue GetZeroVector(QualType VecType); public: - VectorExprEvaluator(EvalInfo &info) : Info(info) {} + VectorExprEvaluator(EvalInfo &info) : ExprEvaluatorBaseTy(info) {} - APValue VisitStmt(Stmt *S) { - return APValue(); - } + APValue Success(const APValue &V, const Expr *E) { return V; } + APValue Error(const Expr *E) { return APValue(); } - APValue VisitParenExpr(ParenExpr *E) - { return Visit(E->getSubExpr()); } - APValue VisitGenericSelectionExpr(GenericSelectionExpr *E) - { return Visit(E->getResultExpr()); } - APValue VisitUnaryExtension(const UnaryOperator *E) - { return Visit(E->getSubExpr()); } - APValue VisitUnaryPlus(const UnaryOperator *E) - { return Visit(E->getSubExpr()); } APValue VisitUnaryReal(const UnaryOperator *E) { return Visit(E->getSubExpr()); } APValue VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) @@ -741,9 +765,6 @@ namespace { APValue VisitCastExpr(const CastExpr* E); APValue VisitCompoundLiteralExpr(const CompoundLiteralExpr *E); APValue VisitInitListExpr(const InitListExpr *E); - APValue VisitConditionalOperator(const ConditionalOperator *E); - APValue VisitChooseExpr(const ChooseExpr *E) - { return Visit(E->getChosenSubExpr(Info.Ctx)); } APValue VisitUnaryImag(const UnaryOperator *E); // FIXME: Missing: unary -, unary ~, binary add/sub/mul/div, // binary comparisons, binary and/or/xor, @@ -756,7 +777,7 @@ namespace { static bool EvaluateVector(const Expr* E, APValue& Result, EvalInfo &Info) { if (!E->getType()->isVectorType()) return false; - Result = VectorExprEvaluator(Info).Visit(const_cast<Expr*>(E)); + Result = VectorExprEvaluator(Info).Visit(E); return !Result.isUninit(); } @@ -792,7 +813,7 @@ APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { } case CK_BitCast: { if (SETy->isVectorType()) - return Visit(const_cast<Expr*>(SE)); + return Visit(SE); if (!SETy->isIntegerType()) return APValue(); @@ -819,7 +840,7 @@ APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { } case CK_LValueToRValue: case CK_NoOp: - return Visit(const_cast<Expr*>(SE)); + return Visit(SE); default: return APValue(); } @@ -827,7 +848,7 @@ APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { APValue VectorExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { - return this->Visit(const_cast<Expr*>(E->getInitializer())); + return this->Visit(E->getInitializer()); } APValue @@ -905,19 +926,6 @@ VectorExprEvaluator::GetZeroVector(QualType T) { return APValue(&Elements[0], Elements.size()); } -APValue VectorExprEvaluator::VisitConditionalOperator(const ConditionalOperator *E) { - bool BoolResult; - if (!HandleConversionToBool(E->getCond(), BoolResult, Info)) - return APValue(); - - Expr* EvalExpr = BoolResult ? E->getTrueExpr() : E->getFalseExpr(); - - APValue Result; - if (EvaluateVector(EvalExpr, Result, Info)) - return Result; - return APValue(); -} - APValue VectorExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { if (!E->getSubExpr()->isEvaluatable(Info.Ctx)) Info.EvalResult.HasSideEffects = true; @@ -930,17 +938,16 @@ APValue VectorExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { namespace { class IntExprEvaluator - : public StmtVisitor<IntExprEvaluator, bool> { - EvalInfo &Info; + : public ExprEvaluatorBase<IntExprEvaluator, bool> { APValue &Result; public: IntExprEvaluator(EvalInfo &info, APValue &result) - : Info(info), Result(result) {} + : ExprEvaluatorBaseTy(info), Result(result) {} bool Success(const llvm::APSInt &SI, const Expr *E) { assert(E->getType()->isIntegralOrEnumerationType() && "Invalid evaluation result."); - assert(SI.isSigned() == E->getType()->isSignedIntegerType() && + assert(SI.isSigned() == E->getType()->isSignedIntegerOrEnumerationType() && "Invalid evaluation result."); assert(SI.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && "Invalid evaluation result."); @@ -954,7 +961,8 @@ public: assert(I.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && "Invalid evaluation result."); Result = APValue(APSInt(I)); - Result.getInt().setIsUnsigned(E->getType()->isUnsignedIntegerType()); + Result.getInt().setIsUnsigned( + E->getType()->isUnsignedIntegerOrEnumerationType()); return true; } @@ -980,23 +988,16 @@ public: return false; } - //===--------------------------------------------------------------------===// - // Visitor Methods - //===--------------------------------------------------------------------===// - - bool VisitStmt(Stmt *) { - assert(0 && "This should be called on integers, stmts are not integers"); - return false; + bool Success(const APValue &V, const Expr *E) { + return Success(V.getInt(), E); } - - bool VisitExpr(Expr *E) { + bool Error(const Expr *E) { return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E); } - bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } - bool VisitGenericSelectionExpr(GenericSelectionExpr *E) { - return Visit(E->getResultExpr()); - } + //===--------------------------------------------------------------------===// + // Visitor Methods + //===--------------------------------------------------------------------===// bool VisitIntegerLiteral(const IntegerLiteral *E) { return Success(E->getValue(), E); @@ -1005,18 +1006,12 @@ public: return Success(E->getValue(), E); } - bool VisitOpaqueValueExpr(OpaqueValueExpr *e) { - const APValue *value = Info.getOpaqueValue(e); - if (!value) { - if (e->getSourceExpr()) return Visit(e->getSourceExpr()); - return Error(e->getExprLoc(), diag::note_invalid_subexpr_in_ice, e); - } - return Success(value->getInt(), e); - } - bool CheckReferencedDecl(const Expr *E, const Decl *D); bool VisitDeclRefExpr(const DeclRefExpr *E) { - return CheckReferencedDecl(E, E->getDecl()); + if (CheckReferencedDecl(E, E->getDecl())) + return true; + + return ExprEvaluatorBaseTy::VisitDeclRefExpr(E); } bool VisitMemberExpr(const MemberExpr *E) { if (CheckReferencedDecl(E, E->getMemberDecl())) { @@ -1024,17 +1019,16 @@ public: Info.EvalResult.HasSideEffects = true; return true; } - return false; + + return ExprEvaluatorBaseTy::VisitMemberExpr(E); } - bool VisitCallExpr(CallExpr *E); + bool VisitCallExpr(const CallExpr *E); bool VisitBinaryOperator(const BinaryOperator *E); bool VisitOffsetOfExpr(const OffsetOfExpr *E); bool VisitUnaryOperator(const UnaryOperator *E); - bool VisitConditionalOperator(const ConditionalOperator *E); - bool VisitBinaryConditionalOperator(const BinaryConditionalOperator *E); - bool VisitCastExpr(CastExpr* E); + bool VisitCastExpr(const CastExpr* E); bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E); bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) { @@ -1069,10 +1063,6 @@ public: return Success(E->getValue(), E); } - bool VisitChooseExpr(const ChooseExpr *E) { - return Visit(E->getChosenSubExpr(Info.Ctx)); - } - bool VisitUnaryReal(const UnaryOperator *E); bool VisitUnaryImag(const UnaryOperator *E); @@ -1083,14 +1073,14 @@ private: CharUnits GetAlignOfExpr(const Expr *E); CharUnits GetAlignOfType(QualType T); static QualType GetObjectType(const Expr *E); - bool TryEvaluateBuiltinObjectSize(CallExpr *E); + bool TryEvaluateBuiltinObjectSize(const CallExpr *E); // FIXME: Missing: array subscript of vector, member of vector }; } // end anonymous namespace static bool EvaluateIntegerOrLValue(const Expr* E, APValue &Result, EvalInfo &Info) { assert(E->getType()->isIntegralOrEnumerationType()); - return IntExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E)); + return IntExprEvaluator(Info, Result).Visit(E); } static bool EvaluateInteger(const Expr* E, APSInt &Result, EvalInfo &Info) { @@ -1114,18 +1104,18 @@ bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) { == Qualifiers::Const) { if (isa<ParmVarDecl>(D)) - return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E); + return false; if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (const Expr *Init = VD->getAnyInitializer()) { if (APValue *V = VD->getEvaluatedValue()) { if (V->isInt()) return Success(V->getInt(), E); - return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E); + return false; } if (VD->isEvaluatingValue()) - return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E); + return false; VD->setEvaluatingValue(); @@ -1144,7 +1134,7 @@ bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) { } // Otherwise, random variable references are not constants. - return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E); + return false; } /// EvaluateBuiltinClassifyType - Evaluate __builtin_classify_type the same way @@ -1216,7 +1206,7 @@ QualType IntExprEvaluator::GetObjectType(const Expr *E) { return QualType(); } -bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(CallExpr *E) { +bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E) { // TODO: Perhaps we should let LLVM lower this? LValue Base; if (!EvaluatePointer(E->getArg(0), Base, Info)) @@ -1244,10 +1234,10 @@ bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(CallExpr *E) { return Success(Size, E); } -bool IntExprEvaluator::VisitCallExpr(CallExpr *E) { +bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { switch (E->isBuiltinCall(Info.Ctx)) { default: - return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E); + return ExprEvaluatorBaseTy::VisitCallExpr(E); case Builtin::BI__builtin_object_size: { if (TryEvaluateBuiltinObjectSize(E)) @@ -1285,7 +1275,7 @@ bool IntExprEvaluator::VisitCallExpr(CallExpr *E) { case Builtin::BI__builtin_strlen: // As an extension, we support strlen() and __builtin_strlen() as constant // expressions when the argument is a string literal. - if (StringLiteral *S + if (const StringLiteral *S = dyn_cast<StringLiteral>(E->getArg(0)->IgnoreParenImpCasts())) { // The string literal may have embedded null characters. Find the first // one and truncate there. @@ -1574,26 +1564,6 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { } } -bool IntExprEvaluator:: -VisitBinaryConditionalOperator(const BinaryConditionalOperator *e) { - OpaqueValueEvaluation opaque(Info, e->getOpaqueValue(), e->getCommon()); - if (opaque.hasError()) return false; - - bool cond; - if (!HandleConversionToBool(e->getCond(), cond, Info)) - return false; - - return Visit(cond ? e->getTrueExpr() : e->getFalseExpr()); -} - -bool IntExprEvaluator::VisitConditionalOperator(const ConditionalOperator *E) { - bool Cond; - if (!HandleConversionToBool(E->getCond(), Cond, Info)) - return false; - - return Visit(Cond ? E->getTrueExpr() : E->getFalseExpr()); -} - CharUnits IntExprEvaluator::GetAlignOfType(QualType T) { // C++ [expr.sizeof]p2: "When applied to a reference or a reference type, // the result is the size of the referenced type." @@ -1679,18 +1649,17 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr( return false; } -bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *E) { +bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) { CharUnits Result; - unsigned n = E->getNumComponents(); - OffsetOfExpr* OOE = const_cast<OffsetOfExpr*>(E); + unsigned n = OOE->getNumComponents(); if (n == 0) return false; - QualType CurrentType = E->getTypeSourceInfo()->getType(); + QualType CurrentType = OOE->getTypeSourceInfo()->getType(); for (unsigned i = 0; i != n; ++i) { OffsetOfExpr::OffsetOfNode ON = OOE->getComponent(i); switch (ON.getKind()) { case OffsetOfExpr::OffsetOfNode::Array: { - Expr *Idx = OOE->getIndexExpr(ON.getArrayExprIndex()); + const Expr *Idx = OOE->getIndexExpr(ON.getArrayExprIndex()); APSInt IdxResult; if (!EvaluateInteger(Idx, IdxResult, Info)) return false; @@ -1745,7 +1714,7 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *E) { } } } - return Success(Result, E); + return Success(Result, OOE); } bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { @@ -1788,8 +1757,8 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { /// HandleCast - This is used to evaluate implicit or explicit casts where the /// result type is integer. -bool IntExprEvaluator::VisitCastExpr(CastExpr *E) { - Expr *SubExpr = E->getSubExpr(); +bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { + const Expr *SubExpr = E->getSubExpr(); QualType DestType = E->getType(); QualType SrcType = SubExpr->getType(); @@ -1936,48 +1905,33 @@ bool IntExprEvaluator::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) { namespace { class FloatExprEvaluator - : public StmtVisitor<FloatExprEvaluator, bool> { - EvalInfo &Info; + : public ExprEvaluatorBase<FloatExprEvaluator, bool> { APFloat &Result; public: FloatExprEvaluator(EvalInfo &info, APFloat &result) - : Info(info), Result(result) {} + : ExprEvaluatorBaseTy(info), Result(result) {} - bool VisitStmt(Stmt *S) { + bool Success(const APValue &V, const Expr *e) { + Result = V.getFloat(); + return true; + } + bool Error(const Stmt *S) { return false; } - bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } - bool VisitGenericSelectionExpr(GenericSelectionExpr *E) { - return Visit(E->getResultExpr()); - } bool VisitCallExpr(const CallExpr *E); bool VisitUnaryOperator(const UnaryOperator *E); bool VisitBinaryOperator(const BinaryOperator *E); bool VisitFloatingLiteral(const FloatingLiteral *E); - bool VisitCastExpr(CastExpr *E); - bool VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E); - bool VisitConditionalOperator(ConditionalOperator *E); - bool VisitBinaryConditionalOperator(BinaryConditionalOperator *E); + bool VisitCastExpr(const CastExpr *E); + bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E); - bool VisitChooseExpr(const ChooseExpr *E) - { return Visit(E->getChosenSubExpr(Info.Ctx)); } - bool VisitUnaryExtension(const UnaryOperator *E) - { return Visit(E->getSubExpr()); } bool VisitUnaryReal(const UnaryOperator *E); bool VisitUnaryImag(const UnaryOperator *E); bool VisitDeclRefExpr(const DeclRefExpr *E); - bool VisitOpaqueValueExpr(const OpaqueValueExpr *e) { - const APValue *value = Info.getOpaqueValue(e); - if (!value) - return (e->getSourceExpr() ? Visit(e->getSourceExpr()) : false); - Result = value->getFloat(); - return true; - } - // FIXME: Missing: array subscript of vector, member of vector, // ImplicitValueInitExpr }; @@ -1985,7 +1939,7 @@ public: static bool EvaluateFloat(const Expr* E, APFloat& Result, EvalInfo &Info) { assert(E->getType()->isRealFloatingType()); - return FloatExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E)); + return FloatExprEvaluator(Info, Result).Visit(E); } static bool TryEvaluateBuiltinNaN(const ASTContext &Context, @@ -2015,7 +1969,9 @@ static bool TryEvaluateBuiltinNaN(const ASTContext &Context, bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { switch (E->isBuiltinCall(Info.Ctx)) { - default: return false; + default: + return ExprEvaluatorBaseTy::VisitCallExpr(E); + case Builtin::BI__builtin_huge_val: case Builtin::BI__builtin_huge_valf: case Builtin::BI__builtin_huge_vall: @@ -2066,6 +2022,9 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { } bool FloatExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { + if (ExprEvaluatorBaseTy::VisitDeclRefExpr(E)) + return true; + const Decl *D = E->getDecl(); if (!isa<VarDecl>(D) || isa<ParmVarDecl>(D)) return false; const VarDecl *VD = cast<VarDecl>(D); @@ -2196,8 +2155,8 @@ bool FloatExprEvaluator::VisitFloatingLiteral(const FloatingLiteral *E) { return true; } -bool FloatExprEvaluator::VisitCastExpr(CastExpr *E) { - Expr* SubExpr = E->getSubExpr(); +bool FloatExprEvaluator::VisitCastExpr(const CastExpr *E) { + const Expr* SubExpr = E->getSubExpr(); switch (E->getCastKind()) { default: @@ -2236,77 +2195,42 @@ bool FloatExprEvaluator::VisitCastExpr(CastExpr *E) { return false; } -bool FloatExprEvaluator::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { +bool FloatExprEvaluator::VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) { Result = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(E->getType())); return true; } -bool FloatExprEvaluator:: -VisitBinaryConditionalOperator(BinaryConditionalOperator *e) { - OpaqueValueEvaluation opaque(Info, e->getOpaqueValue(), e->getCommon()); - if (opaque.hasError()) return false; - - bool cond; - if (!HandleConversionToBool(e->getCond(), cond, Info)) - return false; - - return Visit(cond ? e->getTrueExpr() : e->getFalseExpr()); -} - -bool FloatExprEvaluator::VisitConditionalOperator(ConditionalOperator *E) { - bool Cond; - if (!HandleConversionToBool(E->getCond(), Cond, Info)) - return false; - - return Visit(Cond ? E->getTrueExpr() : E->getFalseExpr()); -} - //===----------------------------------------------------------------------===// // Complex Evaluation (for float and integer) //===----------------------------------------------------------------------===// namespace { class ComplexExprEvaluator - : public StmtVisitor<ComplexExprEvaluator, bool> { - EvalInfo &Info; + : public ExprEvaluatorBase<ComplexExprEvaluator, bool> { ComplexValue &Result; public: ComplexExprEvaluator(EvalInfo &info, ComplexValue &Result) - : Info(info), Result(Result) {} + : ExprEvaluatorBaseTy(info), Result(Result) {} - //===--------------------------------------------------------------------===// - // Visitor Methods - //===--------------------------------------------------------------------===// - - bool VisitStmt(Stmt *S) { + bool Success(const APValue &V, const Expr *e) { + Result.setFrom(V); + return true; + } + bool Error(const Expr *E) { return false; } - bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } - bool VisitGenericSelectionExpr(GenericSelectionExpr *E) { - return Visit(E->getResultExpr()); - } + //===--------------------------------------------------------------------===// + // Visitor Methods + //===--------------------------------------------------------------------===// - bool VisitImaginaryLiteral(ImaginaryLiteral *E); + bool VisitImaginaryLiteral(const ImaginaryLiteral *E); - bool VisitCastExpr(CastExpr *E); + bool VisitCastExpr(const CastExpr *E); bool VisitBinaryOperator(const BinaryOperator *E); bool VisitUnaryOperator(const UnaryOperator *E); - bool VisitConditionalOperator(const ConditionalOperator *E); - bool VisitBinaryConditionalOperator(const BinaryConditionalOperator *E); - bool VisitChooseExpr(const ChooseExpr *E) - { return Visit(E->getChosenSubExpr(Info.Ctx)); } - bool VisitUnaryExtension(const UnaryOperator *E) - { return Visit(E->getSubExpr()); } - bool VisitOpaqueValueExpr(const OpaqueValueExpr *e) { - const APValue *value = Info.getOpaqueValue(e); - if (!value) - return (e->getSourceExpr() ? Visit(e->getSourceExpr()) : false); - Result.setFrom(*value); - return true; - } // FIXME Missing: ImplicitValueInitExpr }; } // end anonymous namespace @@ -2314,11 +2238,11 @@ public: static bool EvaluateComplex(const Expr *E, ComplexValue &Result, EvalInfo &Info) { assert(E->getType()->isAnyComplexType()); - return ComplexExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E)); + return ComplexExprEvaluator(Info, Result).Visit(E); } -bool ComplexExprEvaluator::VisitImaginaryLiteral(ImaginaryLiteral *E) { - Expr* SubExpr = E->getSubExpr(); +bool ComplexExprEvaluator::VisitImaginaryLiteral(const ImaginaryLiteral *E) { + const Expr* SubExpr = E->getSubExpr(); if (SubExpr->getType()->isRealFloatingType()) { Result.makeComplexFloat(); @@ -2342,7 +2266,7 @@ bool ComplexExprEvaluator::VisitImaginaryLiteral(ImaginaryLiteral *E) { } } -bool ComplexExprEvaluator::VisitCastExpr(CastExpr *E) { +bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { case CK_BitCast: @@ -2627,26 +2551,6 @@ bool ComplexExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { } } -bool ComplexExprEvaluator:: -VisitBinaryConditionalOperator(const BinaryConditionalOperator *e) { - OpaqueValueEvaluation opaque(Info, e->getOpaqueValue(), e->getCommon()); - if (opaque.hasError()) return false; - - bool cond; - if (!HandleConversionToBool(e->getCond(), cond, Info)) - return false; - - return Visit(cond ? e->getTrueExpr() : e->getFalseExpr()); -} - -bool ComplexExprEvaluator::VisitConditionalOperator(const ConditionalOperator *E) { - bool Cond; - if (!HandleConversionToBool(E->getCond(), Cond, Info)) - return false; - - return Visit(Cond ? E->getTrueExpr() : E->getFalseExpr()); -} - //===----------------------------------------------------------------------===// // Top level Expr::Evaluate method. //===----------------------------------------------------------------------===// @@ -2655,8 +2559,8 @@ static bool Evaluate(EvalInfo &Info, const Expr *E) { if (E->getType()->isVectorType()) { if (!EvaluateVector(E, Info.EvalResult.Val, Info)) return false; - } else if (E->getType()->isIntegerType()) { - if (!IntExprEvaluator(Info, Info.EvalResult.Val).Visit(const_cast<Expr*>(E))) + } else if (E->getType()->isIntegralOrEnumerationType()) { + if (!IntExprEvaluator(Info, Info.EvalResult.Val).Visit(E)) return false; if (Info.EvalResult.Val.isLValue() && !IsGlobalLValue(Info.EvalResult.Val.getLValueBase())) @@ -2737,7 +2641,7 @@ bool Expr::isEvaluatable(const ASTContext &Ctx) const { bool Expr::HasSideEffects(const ASTContext &Ctx) const { Expr::EvalResult Result; EvalInfo Info(Ctx, Result); - return HasSideEffect(Info).Visit(const_cast<Expr*>(this)); + return HasSideEffect(Info).Visit(this); } APSInt Expr::EvaluateAsInt(const ASTContext &Ctx) const { @@ -2866,6 +2770,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::OpaqueValueExprClass: case Expr::PackExpansionExprClass: case Expr::SubstNonTypeTemplateParmPackExprClass: + case Expr::AsTypeExprClass: return ICEDiag(2, E->getLocStart()); case Expr::SizeOfPackExprClass: @@ -3053,6 +2958,21 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case BO_LAnd: case BO_LOr: { ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx); + + // C++0x [expr.const]p2: + // [...] subexpressions of logical AND (5.14), logical OR + // (5.15), and condi- tional (5.16) operations that are not + // evaluated are not considered. + if (Ctx.getLangOptions().CPlusPlus0x && LHSResult.Val == 0) { + if (Exp->getOpcode() == BO_LAnd && + Exp->getLHS()->EvaluateAsInt(Ctx) == 0) + return LHSResult; + + if (Exp->getOpcode() == BO_LOr && + Exp->getLHS()->EvaluateAsInt(Ctx) != 0) + return LHSResult; + } + ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx); if (LHSResult.Val == 0 && RHSResult.Val == 1) { // Rare case where the RHS has a comma "side-effect"; we need @@ -3111,10 +3031,22 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { return NoDiag(); } ICEDiag CondResult = CheckICE(Exp->getCond(), Ctx); - ICEDiag TrueResult = CheckICE(Exp->getTrueExpr(), Ctx); - ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx); if (CondResult.Val == 2) return CondResult; + + // C++0x [expr.const]p2: + // subexpressions of [...] conditional (5.16) operations that + // are not evaluated are not considered + bool TrueBranch = Ctx.getLangOptions().CPlusPlus0x + ? Exp->getCond()->EvaluateAsInt(Ctx) != 0 + : false; + ICEDiag TrueResult = NoDiag(); + if (!Ctx.getLangOptions().CPlusPlus0x || TrueBranch) + TrueResult = CheckICE(Exp->getTrueExpr(), Ctx); + ICEDiag FalseResult = NoDiag(); + if (!Ctx.getLangOptions().CPlusPlus0x || !TrueBranch) + FalseResult = CheckICE(Exp->getFalseExpr(), Ctx); + if (TrueResult.Val == 2) return TrueResult; if (FalseResult.Val == 2) diff --git a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp index 89bf56d..f428318 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp @@ -57,3 +57,5 @@ ExternalASTSource::FindExternalLexicalDecls(const DeclContext *DC, llvm::SmallVectorImpl<Decl*> &Result) { return true; } + +void ExternalASTSource::getMemoryBufferSizes(MemoryBufferSizes &sizes) const { } diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp index c460929..e81ec7e 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp @@ -255,7 +255,8 @@ private: DeclarationName name, unsigned KnownArity = UnknownArity); - void mangleUnresolvedType(QualType type); + static bool isUnresolvedType(const Type *type); + void mangleUnresolvedType(const Type *type); void mangleName(const TemplateDecl *TD, const TemplateArgument *TemplateArgs, @@ -277,6 +278,7 @@ private: unsigned NumTemplateArgs); void manglePrefix(NestedNameSpecifier *qualifier); void manglePrefix(const DeclContext *DC, bool NoFunction=false); + void manglePrefix(QualType type); void mangleTemplatePrefix(const TemplateDecl *ND); void mangleTemplatePrefix(TemplateName Template); void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity); @@ -317,6 +319,8 @@ private: void mangleTemplateArgs(const TemplateParameterList &PL, const TemplateArgumentList &AL); void mangleTemplateArg(const NamedDecl *P, const TemplateArgument &A); + void mangleUnresolvedTemplateArgs(const TemplateArgument *args, + unsigned numArgs); void mangleTemplateParameter(unsigned Index); @@ -667,7 +671,7 @@ void CXXNameMangler::mangleCallOffset(int64_t NonVirtual, int64_t Virtual) { Out << '_'; } -void CXXNameMangler::mangleUnresolvedType(QualType type) { +void CXXNameMangler::manglePrefix(QualType type) { if (const TemplateSpecializationType *TST = type->getAs<TemplateSpecializationType>()) { if (!mangleSubstitution(QualType(TST, 0))) { @@ -698,6 +702,31 @@ void CXXNameMangler::mangleUnresolvedType(QualType type) { } } +/// Returns true if the given type, appearing within an +/// unresolved-name, should be mangled as an unresolved-type. +bool CXXNameMangler::isUnresolvedType(const Type *type) { + // <unresolved-type> ::= <template-param> + // ::= <decltype> + // ::= <template-template-param> <template-args> + // (this last is not official yet) + + if (isa<TemplateTypeParmType>(type)) return true; + if (isa<DecltypeType>(type)) return true; + // typeof? + if (const TemplateSpecializationType *tst = + dyn_cast<TemplateSpecializationType>(type)) { + TemplateDecl *temp = tst->getTemplateName().getAsTemplateDecl(); + if (temp && isa<TemplateTemplateParmDecl>(temp)) + return true; + } + return false; +} + +void CXXNameMangler::mangleUnresolvedType(const Type *type) { + // This seems to be do everything we want. + mangleType(QualType(type, 0)); +} + /// Mangle everything prior to the base-unresolved-name in an unresolved-name. /// /// \param firstQualifierLookup - the entity found by unqualified lookup @@ -752,17 +781,60 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: { - // Both cases want this. - Out << "sr"; + const Type *type = qualifier->getAsType(); - // We only get here recursively if we're followed by identifiers. - if (recursive) Out << 'N'; + // We only want to use an unresolved-type encoding if this is one of: + // - a decltype + // - a template type parameter + // - a template template parameter with arguments + // In all of these cases, we should have no prefix. + if (qualifier->getPrefix()) { + mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup, + /*recursive*/ true); + } else { + // Otherwise, all the cases want this. + Out << "sr"; - mangleUnresolvedType(QualType(qualifier->getAsType(), 0)); + if (isUnresolvedType(type)) { + // We only get here recursively if we're followed by identifiers. + if (recursive) Out << 'N'; + mangleUnresolvedType(type); - // We never want to print 'E' directly after an unresolved-type, - // so we return directly. - return; + // We never want to print 'E' directly after an unresolved-type, + // so we return directly. + return; + } + } + + assert(!isUnresolvedType(type)); + + // Only certain other types are valid as prefixes; enumerate them. + // FIXME: can we get ElaboratedTypes here? + // FIXME: SubstTemplateTypeParmType? + if (const TagType *t = dyn_cast<TagType>(type)) { + mangleSourceName(t->getDecl()->getIdentifier()); + } else if (const TypedefType *t = dyn_cast<TypedefType>(type)) { + mangleSourceName(t->getDecl()->getIdentifier()); + } else if (const UnresolvedUsingType *t + = dyn_cast<UnresolvedUsingType>(type)) { + mangleSourceName(t->getDecl()->getIdentifier()); + } else if (const DependentNameType *t + = dyn_cast<DependentNameType>(type)) { + mangleSourceName(t->getIdentifier()); + } else if (const TemplateSpecializationType *tst + = dyn_cast<TemplateSpecializationType>(type)) { + TemplateDecl *temp = tst->getTemplateName().getAsTemplateDecl(); + assert(temp && "no template for template specialization type"); + mangleSourceName(temp->getIdentifier()); + mangleUnresolvedTemplateArgs(tst->getArgs(), tst->getNumArgs()); + } else if (const DependentTemplateSpecializationType *tst + = dyn_cast<DependentTemplateSpecializationType>(type)) { + mangleSourceName(tst->getIdentifier()); + mangleUnresolvedTemplateArgs(tst->getArgs(), tst->getNumArgs()); + } else { + llvm_unreachable("unexpected type in nested name specifier!"); + } + break; } case NestedNameSpecifier::Identifier: @@ -1050,6 +1122,12 @@ void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { // := Z <function encoding> E s [<discriminator>] // <discriminator> := _ <non-negative number> const DeclContext *DC = ND->getDeclContext(); + if (isa<ObjCMethodDecl>(DC) && isa<FunctionDecl>(ND)) { + // Don't add objc method name mangling to locally declared function + mangleUnqualifiedName(ND); + return; + } + Out << 'Z'; if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC)) { @@ -1097,7 +1175,7 @@ void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) { case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: - mangleUnresolvedType(QualType(qualifier->getAsType(), 0)); + manglePrefix(QualType(qualifier->getAsType(), 0)); return; case NestedNameSpecifier::Identifier: @@ -1867,6 +1945,22 @@ void CXXNameMangler::mangleType(const DecltypeType *T) { Out << 'E'; } +void CXXNameMangler::mangleType(const UnaryTransformType *T) { + // If this is dependent, we need to record that. If not, we simply + // mangle it as the underlying type since they are equivalent. + if (T->isDependentType()) { + Out << 'U'; + + switch (T->getUTTKind()) { + case UnaryTransformType::EnumUnderlyingType: + Out << "3eut"; + break; + } + } + + mangleType(T->getUnderlyingType()); +} + void CXXNameMangler::mangleType(const AutoType *T) { QualType D = T->getDeducedType(); // <builtin-type> ::= Da # dependent auto @@ -1951,6 +2045,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { // ::= <function-param> // ::= sr <type> <unqualified-name> # dependent name // ::= sr <type> <unqualified-name> <template-args> # dependent template-id + // ::= ds <expression> <expression> # expr.*expr // ::= sZ <template-param> # size of a parameter pack // ::= sZ <function-param> # size of a function parameter pack // ::= <expr-primary> @@ -2005,7 +2100,9 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { case Expr::VAArgExprClass: case Expr::CXXUuidofExprClass: case Expr::CXXNoexceptExprClass: - case Expr::CUDAKernelCallExprClass: { + case Expr::CUDAKernelCallExprClass: + case Expr::AsTypeExprClass: + { // As bad as this diagnostic is, it's better than crashing. Diagnostic &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error, @@ -2227,8 +2324,11 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { case Expr::CompoundAssignOperatorClass: // fallthrough case Expr::BinaryOperatorClass: { const BinaryOperator *BO = cast<BinaryOperator>(E); - mangleOperatorName(BinaryOperator::getOverloadedOperator(BO->getOpcode()), - /*Arity=*/2); + if (BO->getOpcode() == BO_PtrMemD) + Out << "ds"; + else + mangleOperatorName(BinaryOperator::getOverloadedOperator(BO->getOpcode()), + /*Arity=*/2); mangleExpression(BO->getLHS()); mangleExpression(BO->getRHS()); break; @@ -2552,8 +2652,8 @@ void CXXNameMangler::mangleTemplateArgs( const ExplicitTemplateArgumentList &TemplateArgs) { // <template-args> ::= I <template-arg>+ E Out << 'I'; - for (unsigned I = 0, E = TemplateArgs.NumTemplateArgs; I != E; ++I) - mangleTemplateArg(0, TemplateArgs.getTemplateArgs()[I].getArgument()); + for (unsigned i = 0, e = TemplateArgs.NumTemplateArgs; i != e; ++i) + mangleTemplateArg(0, TemplateArgs.getTemplateArgs()[i].getArgument()); Out << 'E'; } @@ -2564,10 +2664,15 @@ void CXXNameMangler::mangleTemplateArgs(TemplateName Template, return mangleTemplateArgs(*TD->getTemplateParameters(), TemplateArgs, NumTemplateArgs); + mangleUnresolvedTemplateArgs(TemplateArgs, NumTemplateArgs); +} + +void CXXNameMangler::mangleUnresolvedTemplateArgs(const TemplateArgument *args, + unsigned numArgs) { // <template-args> ::= I <template-arg>+ E Out << 'I'; - for (unsigned i = 0; i != NumTemplateArgs; ++i) - mangleTemplateArg(0, TemplateArgs[i]); + for (unsigned i = 0; i != numArgs; ++i) + mangleTemplateArg(0, args[i]); Out << 'E'; } diff --git a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp index 3a0b909..c3f3b11 100644 --- a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp @@ -48,6 +48,11 @@ static void checkMangleDC(const DeclContext *DC, const BlockDecl *BD) { const DeclContext *ExpectedDC = BD->getDeclContext(); while (isa<BlockDecl>(ExpectedDC) || isa<EnumDecl>(ExpectedDC)) ExpectedDC = ExpectedDC->getParent(); + // In-class initializers for non-static data members are lexically defined + // within the class, but are mangled as if they were specified as constructor + // member initializers. + if (isa<CXXRecordDecl>(ExpectedDC) && DC != ExpectedDC) + DC = DC->getParent(); assert(DC == ExpectedDC && "Given decl context did not match expected!"); #endif } diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp index 5424beb..4f920f9 100644 --- a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp @@ -1113,6 +1113,10 @@ void MicrosoftCXXNameMangler::mangleType(const DecltypeType *T) { assert(false && "Don't know how to mangle DecltypeTypes yet!"); } +void MicrosoftCXXNameMangler::mangleType(const UnaryTransformType *T) { + assert(false && "Don't know how to mangle UnaryTransformationTypes yet!"); +} + void MicrosoftCXXNameMangler::mangleType(const AutoType *T) { assert(false && "Don't know how to mangle AutoTypes yet!"); } diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp index 0770e1f..de0b1d0 100644 --- a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp @@ -582,7 +582,7 @@ protected: CharUnits NonVirtualSize; CharUnits NonVirtualAlignment; - CharUnits ZeroLengthBitfieldAlignment; + FieldDecl *ZeroLengthBitfield; /// PrimaryBase - the primary base class (if one exists) of the class /// we're laying out. @@ -621,7 +621,7 @@ protected: UnfilledBitsInLastByte(0), MaxFieldAlignment(CharUnits::Zero()), DataSize(0), NonVirtualSize(CharUnits::Zero()), NonVirtualAlignment(CharUnits::One()), - ZeroLengthBitfieldAlignment(CharUnits::Zero()), PrimaryBase(0), + ZeroLengthBitfield(0), PrimaryBase(0), PrimaryBaseIsVirtual(false), FirstNearlyEmptyVBase(0) { } void Layout(const RecordDecl *D); @@ -1258,27 +1258,112 @@ void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) { // Layout each field, for now, just sequentially, respecting alignment. In // the future, this will need to be tweakable by targets. const FieldDecl *LastFD = 0; + ZeroLengthBitfield = 0; + unsigned RemainingInAlignment = 0; for (RecordDecl::field_iterator Field = D->field_begin(), FieldEnd = D->field_end(); Field != FieldEnd; ++Field) { if (IsMsStruct) { - const FieldDecl *FD = (*Field); - if (Context.ZeroBitfieldFollowsBitfield(FD, LastFD)) { - // FIXME. Multiple zero bitfields may follow a bitfield. - // set ZeroLengthBitfieldAlignment to max. of its - // currrent and alignment of 'FD'. - std::pair<CharUnits, CharUnits> FieldInfo = - Context.getTypeInfoInChars(FD->getType()); - ZeroLengthBitfieldAlignment = FieldInfo.second; - continue; - } + FieldDecl *FD = (*Field); + if (Context.ZeroBitfieldFollowsBitfield(FD, LastFD)) + ZeroLengthBitfield = FD; // Zero-length bitfields following non-bitfield members are // ignored: - if (Context.ZeroBitfieldFollowsNonBitfield(FD, LastFD)) + else if (Context.ZeroBitfieldFollowsNonBitfield(FD, LastFD)) continue; + // FIXME. streamline these conditions into a simple one. + else if (Context.BitfieldFollowsBitfield(FD, LastFD) || + Context.BitfieldFollowsNoneBitfield(FD, LastFD) || + Context.NoneBitfieldFollowsBitfield(FD, LastFD)) { + // 1) Adjacent bit fields are packed into the same 1-, 2-, or + // 4-byte allocation unit if the integral types are the same + // size and if the next bit field fits into the current + // allocation unit without crossing the boundary imposed by the + // common alignment requirements of the bit fields. + // 2) Establish a new alignment for a bitfield following + // a non-bitfield if size of their types differ. + // 3) Establish a new alignment for a non-bitfield following + // a bitfield if size of their types differ. + std::pair<uint64_t, unsigned> FieldInfo = + Context.getTypeInfo(FD->getType()); + uint64_t TypeSize = FieldInfo.first; + unsigned FieldAlign = FieldInfo.second; + // This check is needed for 'long long' in -m32 mode. + if (TypeSize > FieldAlign) + FieldAlign = TypeSize; + FieldInfo = Context.getTypeInfo(LastFD->getType()); + uint64_t TypeSizeLastFD = FieldInfo.first; + unsigned FieldAlignLastFD = FieldInfo.second; + // This check is needed for 'long long' in -m32 mode. + if (TypeSizeLastFD > FieldAlignLastFD) + FieldAlignLastFD = TypeSizeLastFD; + + if (TypeSizeLastFD != TypeSize) { + if (RemainingInAlignment && + LastFD && LastFD->isBitField() && + LastFD->getBitWidth()->EvaluateAsInt(Context).getZExtValue()) { + // If previous field was a bitfield with some remaining unfilled + // bits, pad the field so current field starts on its type boundary. + uint64_t FieldOffset = + getDataSizeInBits() - UnfilledBitsInLastByte; + uint64_t NewSizeInBits = RemainingInAlignment + FieldOffset; + setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, + Context.Target.getCharAlign())); + setSize(std::max(getSizeInBits(), getDataSizeInBits())); + RemainingInAlignment = 0; + } + + uint64_t UnpaddedFieldOffset = + getDataSizeInBits() - UnfilledBitsInLastByte; + FieldAlign = std::max(FieldAlign, FieldAlignLastFD); + + // The maximum field alignment overrides the aligned attribute. + if (!MaxFieldAlignment.isZero()) { + unsigned MaxFieldAlignmentInBits = + Context.toBits(MaxFieldAlignment); + FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits); + } + + uint64_t NewSizeInBits = + llvm::RoundUpToAlignment(UnpaddedFieldOffset, FieldAlign); + setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, + Context.Target.getCharAlign())); + UnfilledBitsInLastByte = getDataSizeInBits() - NewSizeInBits; + setSize(std::max(getSizeInBits(), getDataSizeInBits())); + } + if (FD->isBitField()) { + uint64_t FieldSize = + FD->getBitWidth()->EvaluateAsInt(Context).getZExtValue(); + assert (FieldSize > 0 && "LayoutFields - ms_struct layout"); + if (RemainingInAlignment < FieldSize) + RemainingInAlignment = TypeSize - FieldSize; + else + RemainingInAlignment -= FieldSize; + } + } + else if (FD->isBitField()) { + uint64_t FieldSize = + FD->getBitWidth()->EvaluateAsInt(Context).getZExtValue(); + std::pair<uint64_t, unsigned> FieldInfo = + Context.getTypeInfo(FD->getType()); + uint64_t TypeSize = FieldInfo.first; + RemainingInAlignment = TypeSize - FieldSize; + } LastFD = FD; } LayoutField(*Field); } + if (IsMsStruct && RemainingInAlignment && + LastFD && LastFD->isBitField() && + LastFD->getBitWidth()->EvaluateAsInt(Context).getZExtValue()) { + // If we ended a bitfield before the full length of the type then + // pad the struct out to the full length of the last type. + uint64_t FieldOffset = + getDataSizeInBits() - UnfilledBitsInLastByte; + uint64_t NewSizeInBits = RemainingInAlignment + FieldOffset; + setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, + Context.Target.getCharAlign())); + setSize(std::max(getSizeInBits(), getDataSizeInBits())); + } } void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, @@ -1355,6 +1440,27 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { std::pair<uint64_t, unsigned> FieldInfo = Context.getTypeInfo(D->getType()); uint64_t TypeSize = FieldInfo.first; unsigned FieldAlign = FieldInfo.second; + + // This check is needed for 'long long' in -m32 mode. + if (IsMsStruct && (TypeSize > FieldAlign)) + FieldAlign = TypeSize; + + if (ZeroLengthBitfield) { + // If a zero-length bitfield is inserted after a bitfield, + // and the alignment of the zero-length bitfield is + // greater than the member that follows it, `bar', `bar' + // will be aligned as the type of the zero-length bitfield. + if (ZeroLengthBitfield != D) { + std::pair<uint64_t, unsigned> FieldInfo = + Context.getTypeInfo(ZeroLengthBitfield->getType()); + unsigned ZeroLengthBitfieldAlignment = FieldInfo.second; + // Ignore alignment of subsequent zero-length bitfields. + if ((ZeroLengthBitfieldAlignment > FieldAlign) || (FieldSize == 0)) + FieldAlign = ZeroLengthBitfieldAlignment; + if (FieldSize) + ZeroLengthBitfield = 0; + } + } if (FieldSize > TypeSize) { LayoutWideBitField(FieldSize, TypeSize, FieldPacked, D); @@ -1455,11 +1561,21 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { Context.getTypeInfoInChars(D->getType()); FieldSize = FieldInfo.first; FieldAlign = FieldInfo.second; - if (ZeroLengthBitfieldAlignment > FieldAlign) - FieldAlign = ZeroLengthBitfieldAlignment; - ZeroLengthBitfieldAlignment = CharUnits::Zero(); + + if (ZeroLengthBitfield) { + // If a zero-length bitfield is inserted after a bitfield, + // and the alignment of the zero-length bitfield is + // greater than the member that follows it, `bar', `bar' + // will be aligned as the type of the zero-length bitfield. + std::pair<CharUnits, CharUnits> FieldInfo = + Context.getTypeInfoInChars(ZeroLengthBitfield->getType()); + CharUnits ZeroLengthBitfieldAlignment = FieldInfo.second; + if (ZeroLengthBitfieldAlignment > FieldAlign) + FieldAlign = ZeroLengthBitfieldAlignment; + ZeroLengthBitfield = 0; + } - if (Context.getLangOptions().MSBitfields) { + if (Context.getLangOptions().MSBitfields || IsMsStruct) { // If MS bitfield layout is required, figure out what type is being // laid out and align the field to the width of that type. @@ -1641,10 +1757,10 @@ RecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) { if (!RD->isPolymorphic()) return 0; - // A class inside an anonymous namespace doesn't have a key function. (Or + // A class that is not externally visible doesn't have a key function. (Or // at least, there's no point to assigning a key function to such a class; // this doesn't affect the ABI.) - if (RD->isInAnonymousNamespace()) + if (RD->getLinkage() != ExternalLinkage) return 0; // Template instantiations don't have key functions,see Itanium C++ ABI 5.2.6. diff --git a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp index 0d13502..87588e4 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp @@ -1297,7 +1297,7 @@ static const char *getTypeTraitName(UnaryTypeTrait UTT) { case UTT_HasNothrowConstructor: return "__has_nothrow_constructor"; case UTT_HasNothrowCopy: return "__has_nothrow_copy"; case UTT_HasTrivialAssign: return "__has_trivial_assign"; - case UTT_HasTrivialConstructor: return "__has_trivial_constructor"; + case UTT_HasTrivialDefaultConstructor: return "__has_trivial_constructor"; case UTT_HasTrivialCopy: return "__has_trivial_copy"; case UTT_HasTrivialDestructor: return "__has_trivial_destructor"; case UTT_HasVirtualDestructor: return "__has_virtual_destructor"; @@ -1329,6 +1329,7 @@ static const char *getTypeTraitName(UnaryTypeTrait UTT) { case UTT_IsSigned: return "__is_signed"; case UTT_IsStandardLayout: return "__is_standard_layout"; case UTT_IsTrivial: return "__is_trivial"; + case UTT_IsTriviallyCopyable: return "__is_trivially_copyable"; case UTT_IsUnion: return "__is_union"; case UTT_IsUnsigned: return "__is_unsigned"; case UTT_IsVoid: return "__is_void"; @@ -1498,6 +1499,13 @@ void StmtPrinter::VisitBlockDeclRefExpr(BlockDeclRefExpr *Node) { void StmtPrinter::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {} +void StmtPrinter::VisitAsTypeExpr(AsTypeExpr *Node) { + OS << "__builtin_astype("; + PrintExpr(Node->getSrcExpr()); + OS << ", " << Node->getType().getAsString(); + OS << ")"; +} + //===----------------------------------------------------------------------===// // Stmt method implementations //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp index 44818e8..b117cd9 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp @@ -679,6 +679,10 @@ void StmtProfiler::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *S) { VisitCallExpr(S); } +void StmtProfiler::VisitAsTypeExpr(AsTypeExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitCXXNamedCastExpr(CXXNamedCastExpr *S) { VisitExplicitCastExpr(S); } diff --git a/contrib/llvm/tools/clang/lib/AST/Type.cpp b/contrib/llvm/tools/clang/lib/AST/Type.cpp index 9eb497b..d2875528 100644 --- a/contrib/llvm/tools/clang/lib/AST/Type.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Type.cpp @@ -517,7 +517,7 @@ bool Type::isIntegerType() const { if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) // Incomplete enum types are not treated as integer types. // FIXME: In C++, enum types are never integer types. - return ET->getDecl()->isComplete(); + return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped(); return false; } @@ -641,13 +641,27 @@ bool Type::isSignedIntegerType() const { if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) { // Incomplete enum types are not treated as integer types. // FIXME: In C++, enum types are never integer types. - if (ET->getDecl()->isComplete()) + if (ET->getDecl()->isComplete() && !ET->getDecl()->isScoped()) return ET->getDecl()->getIntegerType()->isSignedIntegerType(); } return false; } +bool Type::isSignedIntegerOrEnumerationType() const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) { + return BT->getKind() >= BuiltinType::Char_S && + BT->getKind() <= BuiltinType::Int128; + } + + if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) { + if (ET->getDecl()->isComplete()) + return ET->getDecl()->getIntegerType()->isSignedIntegerType(); + } + + return false; +} + bool Type::hasSignedIntegerRepresentation() const { if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType)) return VT->getElementType()->isSignedIntegerType(); @@ -667,13 +681,27 @@ bool Type::isUnsignedIntegerType() const { if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) { // Incomplete enum types are not treated as integer types. // FIXME: In C++, enum types are never integer types. - if (ET->getDecl()->isComplete()) + if (ET->getDecl()->isComplete() && !ET->getDecl()->isScoped()) return ET->getDecl()->getIntegerType()->isUnsignedIntegerType(); } return false; } +bool Type::isUnsignedIntegerOrEnumerationType() const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) { + return BT->getKind() >= BuiltinType::Bool && + BT->getKind() <= BuiltinType::UInt128; + } + + if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) { + if (ET->getDecl()->isComplete()) + return ET->getDecl()->getIntegerType()->isUnsignedIntegerType(); + } + + return false; +} + bool Type::hasUnsignedIntegerRepresentation() const { if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType)) return VT->getElementType()->isUnsignedIntegerType(); @@ -954,10 +982,37 @@ bool Type::isTrivialType() const { if (const RecordType *RT = BaseTy->getAs<RecordType>()) { if (const CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) { - // C++0x [class]p5: - // A trivial class is a class that has a trivial default constructor - if (!ClassDecl->hasTrivialConstructor()) return false; - // and is trivially copyable. + if (!ClassDecl->isTrivial()) return false; + } + + return true; + } + + // No other types can match. + return false; +} + +bool Type::isTriviallyCopyableType() const { + if (isDependentType()) + return false; + + // C++0x [basic.types]p9 + // Scalar types, trivially copyable class types, arrays of such types, and + // cv-qualified versions of these types are collectively called trivial + // types. + const Type *BaseTy = getBaseElementTypeUnsafe(); + assert(BaseTy && "NULL element type"); + + // Return false for incomplete types after skipping any incomplete array types + // which are expressly allowed by the standard and thus our API. + if (BaseTy->isIncompleteType()) + return false; + + // As an extension, Clang treats vector types as Scalar types. + if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true; + if (const RecordType *RT = BaseTy->getAs<RecordType>()) { + if (const CXXRecordDecl *ClassDecl = + dyn_cast<CXXRecordDecl>(RT->getDecl())) { if (!ClassDecl->isTriviallyCopyable()) return false; } @@ -1027,11 +1082,7 @@ bool Type::isCXX11PODType() const { dyn_cast<CXXRecordDecl>(RT->getDecl())) { // C++11 [class]p10: // A POD struct is a non-union class that is both a trivial class [...] - // C++11 [class]p5: - // A trivial class is a class that has a trivial default constructor - if (!ClassDecl->hasTrivialConstructor()) return false; - // and is trivially copyable. - if (!ClassDecl->isTriviallyCopyable()) return false; + if (!ClassDecl->isTrivial()) return false; // C++11 [class]p10: // A POD struct is a non-union class that is both a trivial class and @@ -1484,6 +1535,16 @@ static TagDecl *getInterestingTagDecl(TagDecl *decl) { return decl; } +UnaryTransformType::UnaryTransformType(QualType BaseType, + QualType UnderlyingType, + UTTKind UKind, + QualType CanonicalType) + : Type(UnaryTransform, CanonicalType, UnderlyingType->isDependentType(), + UnderlyingType->isVariablyModifiedType(), + BaseType->containsUnexpandedParameterPack()) + , BaseType(BaseType), UnderlyingType(UnderlyingType), UKind(UKind) +{} + TagDecl *TagType::getDecl() const { return getInterestingTagDecl(decl); } @@ -1559,13 +1620,13 @@ anyDependentTemplateArguments(const TemplateArgument *Args, unsigned N) { TemplateSpecializationType:: TemplateSpecializationType(TemplateName T, - const TemplateArgument *Args, - unsigned NumArgs, QualType Canon) + const TemplateArgument *Args, unsigned NumArgs, + QualType Canon, QualType AliasedType) : Type(TemplateSpecialization, Canon.isNull()? QualType(this, 0) : Canon, - T.isDependent(), false, T.containsUnexpandedParameterPack()), - Template(T), NumArgs(NumArgs) -{ + Canon.isNull()? T.isDependent() : Canon->isDependentType(), + false, T.containsUnexpandedParameterPack()), + Template(T), NumArgs(NumArgs) { assert(!T.getAsDependentTemplateName() && "Use DependentTemplateSpecializationType for dependent template-name"); assert((!Canon.isNull() || @@ -1576,7 +1637,12 @@ TemplateSpecializationType(TemplateName T, = reinterpret_cast<TemplateArgument *>(this + 1); for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { // Update dependent and variably-modified bits. - if (Args[Arg].isDependent()) + // If the canonical type exists and is non-dependent, the template + // specialization type can be non-dependent even if one of the type + // arguments is. Given: + // template<typename T> using U = int; + // U<T> is always non-dependent, irrespective of the type T. + if (Canon.isNull() && Args[Arg].isDependent()) setDependent(); if (Args[Arg].getKind() == TemplateArgument::Type && Args[Arg].getAsType()->isVariablyModifiedType()) @@ -1586,6 +1652,15 @@ TemplateSpecializationType(TemplateName T, new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]); } + + // Store the aliased type if this is a type alias template specialization. + bool IsTypeAlias = !AliasedType.isNull(); + assert(IsTypeAlias == isTypeAlias() && + "allocated wrong size for type alias"); + if (IsTypeAlias) { + TemplateArgument *Begin = reinterpret_cast<TemplateArgument *>(this + 1); + *reinterpret_cast<QualType*>(Begin + getNumArgs()) = AliasedType; + } } void @@ -1599,6 +1674,11 @@ TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, Args[Idx].Profile(ID, Context); } +bool TemplateSpecializationType::isTypeAlias() const { + TemplateDecl *D = Template.getAsTemplateDecl(); + return D && isa<TypeAliasTemplateDecl>(D); +} + QualType QualifierCollector::apply(const ASTContext &Context, QualType QT) const { if (!hasNonFastQualifiers()) diff --git a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp index 0c5df7f..4519606 100644 --- a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp @@ -94,6 +94,7 @@ void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) { case Type::TypeOfExpr: case Type::TypeOf: case Type::Decltype: + case Type::UnaryTransform: case Type::Record: case Type::Enum: case Type::Elaborated: @@ -512,6 +513,20 @@ void TypePrinter::printDecltype(const DecltypeType *T, std::string &S) { S = "decltype(" + s.str() + ")" + S; } +void TypePrinter::printUnaryTransform(const UnaryTransformType *T, + std::string &S) { + if (!S.empty()) + S = ' ' + S; + std::string Str; + print(T->getBaseType(), Str); + + switch (T->getUTTKind()) { + case UnaryTransformType::EnumUnderlyingType: + S = "__underlying_type(" + Str + ")" + S; + break; + } +} + void TypePrinter::printAuto(const AutoType *T, std::string &S) { // If the type has been deduced, do not print 'auto'. if (T->isDeduced()) { @@ -963,7 +978,7 @@ TemplateSpecializationType::PrintTemplateArgumentList( SpecString += '<'; for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { - if (SpecString.size() > !SkipBrackets) + if (SpecString.size() > unsigned(!SkipBrackets)) SpecString += ", "; // Print the argument into a string. |