diff options
Diffstat (limited to 'lib/Sema/SemaExprCXX.cpp')
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 395 |
1 files changed, 252 insertions, 143 deletions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 0919bc5..3f2cb02 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -13,30 +13,68 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/SemaInternal.h" -#include "clang/Sema/DeclSpec.h" -#include "clang/Sema/Initialization.h" -#include "clang/Sema/Lookup.h" -#include "clang/Sema/ParsedTemplate.h" -#include "clang/Sema/ScopeInfo.h" -#include "clang/Sema/Scope.h" -#include "clang/Sema/TemplateDeduction.h" +#include "TypeLocBuilder.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/CharUnits.h" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/CharUnits.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" -#include "TypeLocBuilder.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/TemplateDeduction.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; using namespace sema; +/// \brief Handle the result of the special case name lookup for inheriting +/// constructor declarations. 'NS::X::X' and 'NS::X<...>::X' are treated as +/// constructor names in member using declarations, even if 'X' is not the +/// name of the corresponding type. +ParsedType Sema::getInheritingConstructorName(CXXScopeSpec &SS, + SourceLocation NameLoc, + IdentifierInfo &Name) { + NestedNameSpecifier *NNS = SS.getScopeRep(); + + // Convert the nested-name-specifier into a type. + QualType Type; + switch (NNS->getKind()) { + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + Type = QualType(NNS->getAsType(), 0); + break; + + case NestedNameSpecifier::Identifier: + // Strip off the last layer of the nested-name-specifier and build a + // typename type for it. + assert(NNS->getAsIdentifier() == &Name && "not a constructor name"); + Type = Context.getDependentNameType(ETK_None, NNS->getPrefix(), + NNS->getAsIdentifier()); + break; + + case NestedNameSpecifier::Global: + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: + llvm_unreachable("Nested name specifier is not a type for inheriting ctor"); + } + + // This reference to the type is located entirely at the location of the + // final identifier in the qualified-id. + return CreateParsedType(Type, + Context.getTrivialTypeSourceInfo(Type, NameLoc)); +} + ParsedType Sema::getDestructorName(SourceLocation TildeLoc, IdentifierInfo &II, SourceLocation NameLoc, @@ -263,8 +301,16 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc, } else if (ObjectTypePtr) Diag(NameLoc, diag::err_ident_in_dtor_not_a_type) << &II; - else - Diag(NameLoc, diag::err_destructor_class_name); + else { + SemaDiagnosticBuilder DtorDiag = Diag(NameLoc, + diag::err_destructor_class_name); + if (S) { + const DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()); + if (const CXXRecordDecl *Class = dyn_cast_or_null<CXXRecordDecl>(Ctx)) + DtorDiag << FixItHint::CreateReplacement(SourceRange(NameLoc), + Class->getNameAsString()); + } + } return ParsedType(); } @@ -336,7 +382,7 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, if (RecordD->isPolymorphic() && E->isGLValue()) { // The subexpression is potentially evaluated; switch the context // and recheck the subexpression. - ExprResult Result = TranformToPotentiallyEvaluated(E); + ExprResult Result = TransformToPotentiallyEvaluated(E); if (Result.isInvalid()) return ExprError(); E = Result.take(); @@ -1041,13 +1087,6 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, } else if (Initializer && isa<InitListExpr>(Initializer)) initStyle = CXXNewExpr::ListInit; else { - // In template instantiation, the initializer could be a CXXDefaultArgExpr - // unwrapped from a CXXConstructExpr that was implicitly built. There is no - // particularly sane way we can handle this (especially since it can even - // occur for array new), so we throw the initializer away and have it be - // rebuilt. - if (Initializer && isa<CXXDefaultArgExpr>(Initializer)) - Initializer = 0; assert((!Initializer || isa<ImplicitValueInitExpr>(Initializer) || isa<CXXConstructExpr>(Initializer)) && "Initializer expression that cannot have been implicitly created."); @@ -1056,20 +1095,20 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, Expr **Inits = &Initializer; unsigned NumInits = Initializer ? 1 : 0; - if (initStyle == CXXNewExpr::CallInit) { - if (ParenListExpr *List = dyn_cast<ParenListExpr>(Initializer)) { - Inits = List->getExprs(); - NumInits = List->getNumExprs(); - } else if (CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Initializer)){ - if (!isa<CXXTemporaryObjectExpr>(CCE)) { - // Can happen in template instantiation. Since this is just an implicit - // construction, we just take it apart and rebuild it. - Inits = CCE->getArgs(); - NumInits = CCE->getNumArgs(); - } - } + if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer)) { + assert(initStyle == CXXNewExpr::CallInit && "paren init for non-call init"); + Inits = List->getExprs(); + NumInits = List->getNumExprs(); } + // Determine whether we've already built the initializer. + bool HaveCompleteInit = false; + if (Initializer && isa<CXXConstructExpr>(Initializer) && + !isa<CXXTemporaryObjectExpr>(Initializer)) + HaveCompleteInit = true; + else if (Initializer && isa<ImplicitValueInitExpr>(Initializer)) + HaveCompleteInit = true; + // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. AutoType *AT = 0; if (TypeMayContainAuto && @@ -1147,7 +1186,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, QualType T) { return S.Diag(Loc, diag::err_array_size_not_integral) - << S.getLangOpts().CPlusPlus0x << T; + << S.getLangOpts().CPlusPlus11 << T; } virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc, @@ -1185,7 +1224,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, QualType T, QualType ConvTy) { return S.Diag(Loc, - S.getLangOpts().CPlusPlus0x + S.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_array_size_conversion : diag::ext_array_size_conversion) << T << ConvTy->isEnumeralType() << ConvTy; @@ -1221,7 +1260,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, if (Value < llvm::APSInt( llvm::APInt::getNullValue(Value.getBitWidth()), Value.isUnsigned())) { - if (getLangOpts().CPlusPlus0x) + if (getLangOpts().CPlusPlus11) Diag(ArraySize->getLocStart(), diag::warn_typecheck_negative_array_new_size) << ArraySize->getSourceRange(); @@ -1233,7 +1272,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, unsigned ActiveSizeBits = ConstantArrayType::getNumAddressingBits(Context, AllocType, Value); if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) { - if (getLangOpts().CPlusPlus0x) + if (getLangOpts().CPlusPlus11) Diag(ArraySize->getLocStart(), diag::warn_array_new_too_large) << Value.toString(10) @@ -1341,9 +1380,12 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, } } + // If we can perform the initialization, and we've not already done so, + // do it now. if (!AllocType->isDependentType() && !Expr::hasAnyTypeDependentArguments( - llvm::makeArrayRef(Inits, NumInits))) { + llvm::makeArrayRef(Inits, NumInits)) && + !HaveCompleteInit) { // C++11 [expr.new]p15: // A new-expression that creates an object of type T initializes that // object as follows: @@ -1379,10 +1421,14 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, } // Mark the new and delete operators as referenced. - if (OperatorNew) + if (OperatorNew) { + DiagnoseUseOfDecl(OperatorNew, StartLoc); MarkFunctionReferenced(StartLoc, OperatorNew); - if (OperatorDelete) + } + if (OperatorDelete) { + DiagnoseUseOfDecl(OperatorDelete, StartLoc); MarkFunctionReferenced(StartLoc, OperatorDelete); + } // C++0x [expr.new]p17: // If the new expression creates an array of objects of class type, @@ -1594,8 +1640,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, EPI.Variadic = Proto->isVariadic(); ExpectedFunctionType - = Context.getFunctionType(Context.VoidTy, ArgTypes.data(), - ArgTypes.size(), EPI); + = Context.getFunctionType(Context.VoidTy, ArgTypes, EPI); } for (LookupResult::iterator D = FoundDelete.begin(), @@ -1641,7 +1686,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, // as a placement deallocation function, would have been // selected as a match for the allocation function, the program // is ill-formed. - if (NumPlaceArgs && getLangOpts().CPlusPlus0x && + if (NumPlaceArgs && getLangOpts().CPlusPlus11 && isNonPlacementDeallocationFunction(OperatorDelete)) { Diag(StartLoc, diag::err_placement_new_non_placement_delete) << SourceRange(PlaceArgs[0]->getLocStart(), @@ -1817,7 +1862,7 @@ void Sema::DeclareGlobalNewDelete() { // lookup. // Note that the C++0x versions of operator delete are deallocation functions, // and thus are implicitly noexcept. - if (!StdBadAlloc && !getLangOpts().CPlusPlus0x) { + if (!StdBadAlloc && !getLangOpts().CPlusPlus11) { // The "std::bad_alloc" class has not yet been declared, so build it // implicitly. StdBadAlloc = CXXRecordDecl::Create(Context, TTK_Class, @@ -1857,8 +1902,8 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, // Check if this function is already declared. { - DeclContext::lookup_iterator Alloc, AllocEnd; - for (llvm::tie(Alloc, AllocEnd) = GlobalCtx->lookup(Name); + DeclContext::lookup_result R = GlobalCtx->lookup(Name); + for (DeclContext::lookup_iterator Alloc = R.begin(), AllocEnd = R.end(); Alloc != AllocEnd; ++Alloc) { // Only look at non-template functions, as it is the predefined, // non-templated allocation function we are trying to declare here. @@ -1880,29 +1925,28 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, bool HasBadAllocExceptionSpec = (Name.getCXXOverloadedOperator() == OO_New || Name.getCXXOverloadedOperator() == OO_Array_New); - if (HasBadAllocExceptionSpec && !getLangOpts().CPlusPlus0x) { + if (HasBadAllocExceptionSpec && !getLangOpts().CPlusPlus11) { assert(StdBadAlloc && "Must have std::bad_alloc declared"); BadAllocType = Context.getTypeDeclType(getStdBadAlloc()); } FunctionProtoType::ExtProtoInfo EPI; if (HasBadAllocExceptionSpec) { - if (!getLangOpts().CPlusPlus0x) { + if (!getLangOpts().CPlusPlus11) { EPI.ExceptionSpecType = EST_Dynamic; EPI.NumExceptions = 1; EPI.Exceptions = &BadAllocType; } } else { - EPI.ExceptionSpecType = getLangOpts().CPlusPlus0x ? + EPI.ExceptionSpecType = getLangOpts().CPlusPlus11 ? EST_BasicNoexcept : EST_DynamicNone; } - QualType FnType = Context.getFunctionType(Return, &Argument, 1, EPI); + QualType FnType = Context.getFunctionType(Return, Argument, EPI); FunctionDecl *Alloc = FunctionDecl::Create(Context, GlobalCtx, SourceLocation(), SourceLocation(), Name, - FnType, /*TInfo=*/0, SC_None, - SC_None, false, true); + FnType, /*TInfo=*/0, SC_None, false, true); Alloc->setImplicit(); if (AddMallocAttr) @@ -1911,7 +1955,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(), SourceLocation(), 0, Argument, /*TInfo=*/0, - SC_None, SC_None, 0); + SC_None, 0); Alloc->setParams(Param); // FIXME: Also add this declaration to the IdentifierResolver, but @@ -2030,6 +2074,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, if (!Ex.get()->isTypeDependent()) { // Perform lvalue-to-rvalue cast, if needed. Ex = DefaultLvalueConversion(Ex.take()); + if (Ex.isInvalid()) + return ExprError(); QualType Type = Ex.get()->getType(); @@ -2041,9 +2087,11 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, SmallVector<CXXConversionDecl*, 4> ObjectPtrConversions; CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl()); - const UnresolvedSetImpl *Conversions = RD->getVisibleConversionFunctions(); - for (UnresolvedSetImpl::iterator I = Conversions->begin(), - E = Conversions->end(); I != E; ++I) { + std::pair<CXXRecordDecl::conversion_iterator, + CXXRecordDecl::conversion_iterator> + Conversions = RD->getVisibleConversionFunctions(); + for (CXXRecordDecl::conversion_iterator + I = Conversions.first, E = Conversions.second; I != E; ++I) { NamedDecl *D = I.getDecl(); if (isa<UsingShadowDecl>(D)) D = cast<UsingShadowDecl>(D)->getTargetDecl(); @@ -2323,11 +2371,11 @@ static ExprResult BuildCXXCastArgument(Sema &S, S.CheckConstructorAccess(CastLoc, Constructor, InitializedEntity::InitializeTemporary(Ty), Constructor->getAccess()); - + ExprResult Result = S.BuildCXXConstructExpr(CastLoc, Ty, cast<CXXConstructorDecl>(Method), - ConstructorArgs, - HadMultipleCandidates, /*ZeroInit*/ false, + ConstructorArgs, HadMultipleCandidates, + /*ListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); if (Result.isInvalid()) return ExprError(); @@ -2479,14 +2527,14 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, ToType, SCS.CopyConstructor, ConstructorArgs, /*HadMultipleCandidates*/ false, - /*ZeroInit*/ false, + /*ListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); } return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), ToType, SCS.CopyConstructor, From, /*HadMultipleCandidates*/ false, - /*ZeroInit*/ false, + /*ListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); } @@ -2782,6 +2830,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, break; } + case ICK_Zero_Event_Conversion: + From = ImpCastExprToType(From, ToType, + CK_ZeroToOCLEvent, + From->getValueKind()).take(); + break; + case ICK_Lvalue_To_Rvalue: case ICK_Array_To_Pointer: case ICK_Function_To_Pointer: @@ -2920,10 +2974,13 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, // type due to the overarching C++0x type predicates being implemented // requiring the complete type. case UTT_HasNothrowAssign: + case UTT_HasNothrowMoveAssign: case UTT_HasNothrowConstructor: case UTT_HasNothrowCopy: case UTT_HasTrivialAssign: + case UTT_HasTrivialMoveAssign: case UTT_HasTrivialDefaultConstructor: + case UTT_HasTrivialMoveConstructor: case UTT_HasTrivialCopy: case UTT_HasTrivialDestructor: case UTT_HasVirtualDestructor: @@ -2942,6 +2999,42 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, llvm_unreachable("Type trait not handled by switch"); } +static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op, + Sema &Self, SourceLocation KeyLoc, ASTContext &C, + bool (CXXRecordDecl::*HasTrivial)() const, + bool (CXXRecordDecl::*HasNonTrivial)() const, + bool (CXXMethodDecl::*IsDesiredOp)() const) +{ + CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + if ((RD->*HasTrivial)() && !(RD->*HasNonTrivial)()) + return true; + + DeclarationName Name = C.DeclarationNames.getCXXOperatorName(Op); + DeclarationNameInfo NameInfo(Name, KeyLoc); + LookupResult Res(Self, NameInfo, Sema::LookupOrdinaryName); + if (Self.LookupQualifiedName(Res, RD)) { + bool FoundOperator = false; + Res.suppressDiagnostics(); + for (LookupResult::iterator Op = Res.begin(), OpEnd = Res.end(); + Op != OpEnd; ++Op) { + if (isa<FunctionTemplateDecl>(*Op)) + continue; + + CXXMethodDecl *Operator = cast<CXXMethodDecl>(*Op); + if((Operator->*IsDesiredOp)()) { + FoundOperator = true; + const FunctionProtoType *CPT = + Operator->getType()->getAs<FunctionProtoType>(); + CPT = Self.ResolveExceptionSpec(KeyLoc, CPT); + if (!CPT || !CPT->isNothrow(Self.Context)) + return false; + } + } + return FoundOperator; + } + return false; +} + static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, SourceLocation KeyLoc, QualType T) { assert(!T->isDependentType() && "Cannot evaluate traits of dependent type"); @@ -3060,6 +3153,13 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, // // 1: http://gcc.gnu/.org/onlinedocs/gcc/Type-Traits.html // 2: http://docwiki.embarcadero.com/RADStudio/XE/en/Type_Trait_Functions_(C%2B%2B0x)_Index + // + // Note that these builtins do not behave as documented in g++: if a class + // has both a trivial and a non-trivial special member of a particular kind, + // they return false! For now, we emulate this behavior. + // FIXME: This appears to be a g++ bug: more complex cases reveal that it + // does not correctly compute triviality in the presence of multiple special + // members of the same kind. Revisit this once the g++ bug is fixed. case UTT_HasTrivialDefaultConstructor: // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: // If __is_pod (type) is true then the trait is true, else if type is @@ -3067,9 +3167,18 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, // constructor ([class.ctor]) then the trait is true, else it is false. if (T.isPODType(Self.Context)) return true; - if (const RecordType *RT = - C.getBaseElementType(T)->getAs<RecordType>()) - return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDefaultConstructor(); + if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) + return RD->hasTrivialDefaultConstructor() && + !RD->hasNonTrivialDefaultConstructor(); + return false; + case UTT_HasTrivialMoveConstructor: + // This trait is implemented by MSVC 2012 and needed to parse the + // standard library headers. Specifically this is used as the logic + // behind std::is_trivially_move_constructible (20.9.4.3). + if (T.isPODType(Self.Context)) + return true; + if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) + return RD->hasTrivialMoveConstructor() && !RD->hasNonTrivialMoveConstructor(); return false; case UTT_HasTrivialCopy: // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: @@ -3079,8 +3188,18 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, // is true, else it is false. if (T.isPODType(Self.Context) || T->isReferenceType()) return true; - if (const RecordType *RT = T->getAs<RecordType>()) - return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyConstructor(); + if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + return RD->hasTrivialCopyConstructor() && + !RD->hasNonTrivialCopyConstructor(); + return false; + case UTT_HasTrivialMoveAssign: + // This trait is implemented by MSVC 2012 and needed to parse the + // standard library headers. Specifically it is used as the logic + // behind std::is_trivially_move_assignable (20.9.4.3) + if (T.isPODType(Self.Context)) + return true; + if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) + return RD->hasTrivialMoveAssignment() && !RD->hasNonTrivialMoveAssignment(); return false; case UTT_HasTrivialAssign: // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: @@ -3095,12 +3214,13 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, // errors if the copy assignment operator is actually used, q.v. // [class.copy]p12). - if (C.getBaseElementType(T).isConstQualified()) + if (T.isConstQualified()) return false; if (T.isPODType(Self.Context)) return true; - if (const RecordType *RT = T->getAs<RecordType>()) - return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyAssignment(); + if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + return RD->hasTrivialCopyAssignment() && + !RD->hasNonTrivialCopyAssignment(); return false; case UTT_HasTrivialDestructor: // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: @@ -3117,9 +3237,8 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, T.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) return true; - if (const RecordType *RT = - C.getBaseElementType(T)->getAs<RecordType>()) - return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor(); + if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) + return RD->hasTrivialDestructor(); return false; // TODO: Propagate nothrowness for implicitly declared special members. case UTT_HasNothrowAssign: @@ -3135,39 +3254,26 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, if (T->isReferenceType()) return false; if (T.isPODType(Self.Context) || T->isObjCLifetimeType()) - return true; - if (const RecordType *RT = T->getAs<RecordType>()) { - CXXRecordDecl* RD = cast<CXXRecordDecl>(RT->getDecl()); - if (RD->hasTrivialCopyAssignment()) - return true; + return true; - bool FoundAssign = false; - DeclarationName Name = C.DeclarationNames.getCXXOperatorName(OO_Equal); - LookupResult Res(Self, DeclarationNameInfo(Name, KeyLoc), - Sema::LookupOrdinaryName); - if (Self.LookupQualifiedName(Res, RD)) { - Res.suppressDiagnostics(); - for (LookupResult::iterator Op = Res.begin(), OpEnd = Res.end(); - Op != OpEnd; ++Op) { - if (isa<FunctionTemplateDecl>(*Op)) - continue; - - CXXMethodDecl *Operator = cast<CXXMethodDecl>(*Op); - if (Operator->isCopyAssignmentOperator()) { - FoundAssign = true; - const FunctionProtoType *CPT - = Operator->getType()->getAs<FunctionProtoType>(); - CPT = Self.ResolveExceptionSpec(KeyLoc, CPT); - if (!CPT) - return false; - if (!CPT->isNothrow(Self.Context)) - return false; - } - } - } - - return FoundAssign; - } + if (const RecordType *RT = T->getAs<RecordType>()) + return HasNoThrowOperator(RT, OO_Equal, Self, KeyLoc, C, + &CXXRecordDecl::hasTrivialCopyAssignment, + &CXXRecordDecl::hasNonTrivialCopyAssignment, + &CXXMethodDecl::isCopyAssignmentOperator); + return false; + case UTT_HasNothrowMoveAssign: + // This trait is implemented by MSVC 2012 and needed to parse the + // standard library headers. Specifically this is used as the logic + // behind std::is_nothrow_move_assignable (20.9.4.3). + if (T.isPODType(Self.Context)) + return true; + + if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>()) + return HasNoThrowOperator(RT, OO_Equal, Self, KeyLoc, C, + &CXXRecordDecl::hasTrivialMoveAssignment, + &CXXRecordDecl::hasNonTrivialMoveAssignment, + &CXXMethodDecl::isMoveAssignmentOperator); return false; case UTT_HasNothrowCopy: // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: @@ -3177,16 +3283,16 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, // false. if (T.isPODType(C) || T->isReferenceType() || T->isObjCLifetimeType()) return true; - if (const RecordType *RT = T->getAs<RecordType>()) { - CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - if (RD->hasTrivialCopyConstructor()) + if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) { + if (RD->hasTrivialCopyConstructor() && + !RD->hasNonTrivialCopyConstructor()) return true; bool FoundConstructor = false; unsigned FoundTQs; - DeclContext::lookup_const_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD); - Con != ConEnd; ++Con) { + DeclContext::lookup_const_result R = Self.LookupConstructors(RD); + for (DeclContext::lookup_const_iterator Con = R.begin(), + ConEnd = R.end(); Con != ConEnd; ++Con) { // A template constructor is never a copy constructor. // FIXME: However, it may actually be selected at the actual overload // resolution point. @@ -3218,14 +3324,14 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, // throw an exception then the trait is true, else it is false. if (T.isPODType(C) || T->isObjCLifetimeType()) return true; - if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>()) { - CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - if (RD->hasTrivialDefaultConstructor()) + if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) { + if (RD->hasTrivialDefaultConstructor() && + !RD->hasNonTrivialDefaultConstructor()) return true; - DeclContext::lookup_const_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD); - Con != ConEnd; ++Con) { + DeclContext::lookup_const_result R = Self.LookupConstructors(RD); + for (DeclContext::lookup_const_iterator Con = R.begin(), + ConEnd = R.end(); Con != ConEnd; ++Con) { // FIXME: In C++0x, a constructor template can be a default constructor. if (isa<FunctionTemplateDecl>(*Con)) continue; @@ -3247,11 +3353,9 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: // If type is a class type with a virtual destructor ([class.dtor]) // then the trait is true, else it is false. - if (const RecordType *Record = T->getAs<RecordType>()) { - CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl()); + if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) if (CXXDestructorDecl *Destructor = Self.LookupDestructor(RD)) return Destructor->isVirtual(); - } return false; // These type trait expressions are modeled on the specifications for the @@ -3360,8 +3464,8 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, if (SawVoid) return false; - llvm::SmallVector<OpaqueValueExpr, 2> OpaqueArgExprs; - llvm::SmallVector<Expr *, 2> ArgExprs; + SmallVector<OpaqueValueExpr, 2> OpaqueArgExprs; + SmallVector<Expr *, 2> ArgExprs; ArgExprs.reserve(Args.size() - 1); for (unsigned I = 1, N = Args.size(); I != N; ++I) { QualType T = Args[I]->getType(); @@ -3428,7 +3532,7 @@ ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc, ExprResult Sema::ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc, ArrayRef<ParsedType> Args, SourceLocation RParenLoc) { - llvm::SmallVector<TypeSourceInfo *, 4> ConvertedArgs; + SmallVector<TypeSourceInfo *, 4> ConvertedArgs; ConvertedArgs.reserve(Args.size()); for (unsigned I = 0, N = Args.size(); I != N; ++I) { @@ -4769,7 +4873,7 @@ Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) { // a StmtExpr; currently this is only used for asm statements. // This is hacky, either create a new CXXStmtWithTemporaries statement or // a new AsmStmtWithTemporaries. - CompoundStmt *CompStmt = new (Context) CompoundStmt(Context, &SubStmt, 1, + CompoundStmt *CompStmt = new (Context) CompoundStmt(Context, SubStmt, SourceLocation(), SourceLocation()); Expr *E = new (Context) StmtExpr(CompStmt, Context.VoidTy, SourceLocation(), @@ -4782,8 +4886,7 @@ Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) { /// are omitted for the 'topmost' call in the decltype expression. If the /// topmost call bound a temporary, strip that temporary off the expression. ExprResult Sema::ActOnDecltypeExpression(Expr *E) { - ExpressionEvaluationContextRecord &Rec = ExprEvalContexts.back(); - assert(Rec.IsDecltype && "not in a decltype expression"); + assert(ExprEvalContexts.back().IsDecltype && "not in a decltype expression"); // C++11 [expr.call]p11: // If a function call is a prvalue of object type, @@ -4824,7 +4927,7 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) { E = TopBind->getSubExpr(); // Disable the special decltype handling now. - Rec.IsDecltype = false; + ExprEvalContexts.back().IsDecltype = false; // In MS mode, don't perform any extra checking of call return types within a // decltype expression. @@ -4833,8 +4936,9 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) { // Perform the semantic checks we delayed until this point. CallExpr *TopCall = dyn_cast<CallExpr>(E); - for (unsigned I = 0, N = Rec.DelayedDecltypeCalls.size(); I != N; ++I) { - CallExpr *Call = Rec.DelayedDecltypeCalls[I]; + for (unsigned I = 0, N = ExprEvalContexts.back().DelayedDecltypeCalls.size(); + I != N; ++I) { + CallExpr *Call = ExprEvalContexts.back().DelayedDecltypeCalls[I]; if (Call == TopCall) continue; @@ -4846,8 +4950,10 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) { // Now all relevant types are complete, check the destructors are accessible // and non-deleted, and annotate them on the temporaries. - for (unsigned I = 0, N = Rec.DelayedDecltypeBinds.size(); I != N; ++I) { - CXXBindTemporaryExpr *Bind = Rec.DelayedDecltypeBinds[I]; + for (unsigned I = 0, N = ExprEvalContexts.back().DelayedDecltypeBinds.size(); + I != N; ++I) { + CXXBindTemporaryExpr *Bind = + ExprEvalContexts.back().DelayedDecltypeBinds[I]; if (Bind == TopBind) continue; @@ -5321,12 +5427,12 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, VK_RValue, OK_Ordinary); if (HadMultipleCandidates) ME->setHadMultipleCandidates(true); + MarkMemberReferenced(ME); QualType ResultType = Method->getResultType(); ExprValueKind VK = Expr::getValueKindForType(ResultType); ResultType = ResultType.getNonLValueExprType(Context); - MarkFunctionReferenced(Exp.get()->getLocStart(), Method); CXXMemberCallExpr *CE = new (Context) CXXMemberCallExpr(Context, ME, MultiExprArg(), ResultType, VK, Exp.get()->getLocEnd()); @@ -5429,7 +5535,7 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) { // normally, we don't need to do anything to handle it, but if it is a // volatile lvalue with a special form, we perform an lvalue-to-rvalue // conversion. - if (getLangOpts().CPlusPlus0x && E->isGLValue() && + if (getLangOpts().CPlusPlus11 && E->isGLValue() && E->getType().isVolatileQualified() && IsSpecialDiscardedValue(E)) { ExprResult Res = DefaultLvalueConversion(E); @@ -5460,7 +5566,9 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) { return Owned(E); } -ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC) { +ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC, + bool DiscardedValue, + bool IsConstexpr) { ExprResult FullExpr = Owned(FE); if (!FullExpr.get()) @@ -5469,24 +5577,25 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC) { if (DiagnoseUnexpandedParameterPack(FullExpr.get())) return ExprError(); - // Top-level message sends default to 'id' when we're in a debugger. - if (getLangOpts().DebuggerCastResultToId && - FullExpr.get()->getType() == Context.UnknownAnyTy && - isa<ObjCMessageExpr>(FullExpr.get())) { + // Top-level expressions default to 'id' when we're in a debugger. + if (DiscardedValue && getLangOpts().DebuggerCastResultToId && + FullExpr.get()->getType() == Context.UnknownAnyTy) { FullExpr = forceUnknownAnyToType(FullExpr.take(), Context.getObjCIdType()); if (FullExpr.isInvalid()) return ExprError(); } - - FullExpr = CheckPlaceholderExpr(FullExpr.take()); - if (FullExpr.isInvalid()) - return ExprError(); - FullExpr = IgnoredValueConversions(FullExpr.take()); - if (FullExpr.isInvalid()) - return ExprError(); + if (DiscardedValue) { + FullExpr = CheckPlaceholderExpr(FullExpr.take()); + if (FullExpr.isInvalid()) + return ExprError(); + + FullExpr = IgnoredValueConversions(FullExpr.take()); + if (FullExpr.isInvalid()) + return ExprError(); + } - CheckImplicitConversions(FullExpr.get(), CC); + CheckCompletedExpr(FullExpr.get(), CC, IsConstexpr); return MaybeCreateExprWithCleanups(FullExpr); } |