diff options
Diffstat (limited to 'lib/AST/DeclCXX.cpp')
-rw-r--r-- | lib/AST/DeclCXX.cpp | 198 |
1 files changed, 138 insertions, 60 deletions
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 0646499..a17abdd 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -10,9 +10,9 @@ // This file implements the C++ related Decl classes. // //===----------------------------------------------------------------------===// - #include "clang/AST/DeclCXX.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclTemplate.h" @@ -35,6 +35,17 @@ AccessSpecDecl *AccessSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (Mem) AccessSpecDecl(EmptyShell()); } +void LazyASTUnresolvedSet::getFromExternalSource(ASTContext &C) const { + ExternalASTSource *Source = C.getExternalSource(); + assert(Impl.Decls.isLazy() && "getFromExternalSource for non-lazy set"); + assert(Source && "getFromExternalSource with no external source"); + + for (ASTUnresolvedSet::iterator I = Impl.begin(); I != Impl.end(); ++I) + I.setDecl(cast<NamedDecl>(Source->GetExternalDecl( + reinterpret_cast<uintptr_t>(I.getDecl()) >> 2))); + Impl.Decls.setLazy(false); +} + CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) : UserDeclaredConstructor(false), UserDeclaredSpecialMembers(0), Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false), @@ -60,9 +71,8 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) ImplicitCopyAssignmentHasConstParam(true), HasDeclaredCopyConstructorWithConstParam(false), HasDeclaredCopyAssignmentWithConstParam(false), - FailedImplicitMoveConstructor(false), FailedImplicitMoveAssignment(false), IsLambda(false), NumBases(0), NumVBases(0), Bases(), VBases(), - Definition(D), FirstFriend(0) { + Definition(D), FirstFriend() { } CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase() const { @@ -97,12 +107,17 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, CXXRecordDecl *CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, TypeSourceInfo *Info, SourceLocation Loc, - bool Dependent) { + bool Dependent, bool IsGeneric, + LambdaCaptureDefault CaptureDefault) { CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TTK_Class, DC, Loc, Loc, 0, 0); R->IsBeingDefined = true; - R->DefinitionData = new (C) struct LambdaDefinitionData(R, Info, Dependent); + R->DefinitionData = new (C) struct LambdaDefinitionData(R, Info, + Dependent, + IsGeneric, + CaptureDefault); R->MayHaveOutOfDateDef = false; + R->setImplicit(true); C.getTypeDeclType(R, /*PrevDecl=*/0); return R; } @@ -552,18 +567,16 @@ void CXXRecordDecl::addedMember(Decl *D) { if (Conversion->getPrimaryTemplate()) { // We don't record specializations. - } else if (FunTmpl) { - if (FunTmpl->getPreviousDecl()) - data().Conversions.replace(FunTmpl->getPreviousDecl(), - FunTmpl, AS); - else - data().Conversions.addDecl(getASTContext(), FunTmpl, AS); } else { - if (Conversion->getPreviousDecl()) - data().Conversions.replace(Conversion->getPreviousDecl(), - Conversion, AS); + ASTContext &Ctx = getASTContext(); + ASTUnresolvedSet &Conversions = data().Conversions.get(Ctx); + NamedDecl *Primary = + FunTmpl ? cast<NamedDecl>(FunTmpl) : cast<NamedDecl>(Conversion); + if (Primary->getPreviousDecl()) + Conversions.replace(cast<NamedDecl>(Primary->getPreviousDecl()), + Primary, AS); else - data().Conversions.addDecl(getASTContext(), Conversion, AS); + Conversions.addDecl(Ctx, Primary, AS); } } @@ -662,7 +675,7 @@ void CXXRecordDecl::addedMember(Decl *D) { if (!Context.getLangOpts().ObjCAutoRefCount || T.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) setHasObjectMember(true); - } else if (!T.isPODType(Context)) + } else if (!T.isCXX98PODType(Context)) data().PlainOldData = false; if (T->isReferenceType()) { @@ -712,6 +725,13 @@ void CXXRecordDecl::addedMember(Decl *D) { if (FieldRec->getDefinition()) { addedClassSubobject(FieldRec); + // We may need to perform overload resolution to determine whether a + // field can be moved if it's const or volatile qualified. + if (T.getCVRQualifiers() & (Qualifiers::Const | Qualifiers::Volatile)) { + data().NeedOverloadResolutionForMoveConstructor = true; + data().NeedOverloadResolutionForMoveAssignment = true; + } + // C++11 [class.ctor]p5, C++11 [class.copy]p11: // A defaulted [special member] for a class X is defined as // deleted if: @@ -880,10 +900,13 @@ void CXXRecordDecl::addedMember(Decl *D) { } // Handle using declarations of conversion functions. - if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(D)) + if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(D)) { if (Shadow->getDeclName().getNameKind() - == DeclarationName::CXXConversionFunctionName) - data().Conversions.addDecl(getASTContext(), Shadow, Shadow->getAccess()); + == DeclarationName::CXXConversionFunctionName) { + ASTContext &Ctx = getASTContext(); + data().Conversions.get(Ctx).addDecl(Ctx, Shadow, Shadow->getAccess()); + } + } } void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) { @@ -929,6 +952,43 @@ bool CXXRecordDecl::isCLike() const { return isPOD() && data().HasOnlyCMembers; } + +bool CXXRecordDecl::isGenericLambda() const { + if (!isLambda()) return false; + return getLambdaData().IsGenericLambda; +} + +CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const { + if (!isLambda()) return 0; + DeclarationName Name = + getASTContext().DeclarationNames.getCXXOperatorName(OO_Call); + DeclContext::lookup_const_result Calls = lookup(Name); + + assert(!Calls.empty() && "Missing lambda call operator!"); + assert(Calls.size() == 1 && "More than one lambda call operator!"); + + NamedDecl *CallOp = Calls.front(); + if (FunctionTemplateDecl *CallOpTmpl = + dyn_cast<FunctionTemplateDecl>(CallOp)) + return cast<CXXMethodDecl>(CallOpTmpl->getTemplatedDecl()); + + return cast<CXXMethodDecl>(CallOp); +} + +CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const { + if (!isLambda()) return 0; + DeclarationName Name = + &getASTContext().Idents.get(getLambdaStaticInvokerName()); + DeclContext::lookup_const_result Invoker = lookup(Name); + if (Invoker.empty()) return 0; + assert(Invoker.size() == 1 && "More than one static invoker operator!"); + NamedDecl *InvokerFun = Invoker.front(); + if (FunctionTemplateDecl *InvokerTemplate = + dyn_cast<FunctionTemplateDecl>(InvokerFun)) + return cast<CXXMethodDecl>(InvokerTemplate->getTemplatedDecl()); + + return cast<CXXMethodDecl>(InvokerFun); +} void CXXRecordDecl::getCaptureFields( llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures, @@ -940,15 +1000,22 @@ void CXXRecordDecl::getCaptureFields( RecordDecl::field_iterator Field = field_begin(); for (LambdaExpr::Capture *C = Lambda.Captures, *CEnd = C + Lambda.NumCaptures; C != CEnd; ++C, ++Field) { - if (C->capturesThis()) { + if (C->capturesThis()) ThisCapture = *Field; - continue; - } - - Captures[C->getCapturedVar()] = *Field; + else if (C->capturesVariable()) + Captures[C->getCapturedVar()] = *Field; } + assert(Field == field_end()); } +TemplateParameterList * +CXXRecordDecl::getGenericLambdaTemplateParameterList() const { + if (!isLambda()) return 0; + CXXMethodDecl *CallOp = getLambdaCallOperator(); + if (FunctionTemplateDecl *Tmpl = CallOp->getDescribedFunctionTemplate()) + return Tmpl->getTemplateParameters(); + return 0; +} static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) { QualType T; @@ -1085,16 +1152,21 @@ static void CollectVisibleConversions(ASTContext &Context, /// in current class; including conversion function templates. std::pair<CXXRecordDecl::conversion_iterator,CXXRecordDecl::conversion_iterator> CXXRecordDecl::getVisibleConversionFunctions() { - // If root class, all conversions are visible. - if (bases_begin() == bases_end()) - return std::make_pair(data().Conversions.begin(), data().Conversions.end()); - // If visible conversion list is already evaluated, return it. - if (!data().ComputedVisibleConversions) { - CollectVisibleConversions(getASTContext(), this, data().VisibleConversions); - data().ComputedVisibleConversions = true; + ASTContext &Ctx = getASTContext(); + + ASTUnresolvedSet *Set; + if (bases_begin() == bases_end()) { + // If root class, all conversions are visible. + Set = &data().Conversions.get(Ctx); + } else { + Set = &data().VisibleConversions.get(Ctx); + // If visible conversion list is not evaluated, evaluate it. + if (!data().ComputedVisibleConversions) { + CollectVisibleConversions(Ctx, this, *Set); + data().ComputedVisibleConversions = true; + } } - return std::make_pair(data().VisibleConversions.begin(), - data().VisibleConversions.end()); + return std::make_pair(Set->begin(), Set->end()); } void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) { @@ -1109,7 +1181,7 @@ void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) { // with sufficiently large numbers of directly-declared conversions // that asymptotic behavior matters. - ASTUnresolvedSet &Convs = data().Conversions; + ASTUnresolvedSet &Convs = data().Conversions.get(getASTContext()); for (unsigned I = 0, E = Convs.size(); I != E; ++I) { if (Convs[I].getDecl() == ConvDecl) { Convs.erase(I); @@ -1134,7 +1206,7 @@ CXXRecordDecl::setInstantiationOfMemberClass(CXXRecordDecl *RD, TemplateSpecializationKind TSK) { assert(TemplateOrInstantiation.isNull() && "Previous template or instantiation?"); - assert(!isa<ClassTemplateSpecializationDecl>(this)); + assert(!isa<ClassTemplatePartialSpecializationDecl>(this)); TemplateOrInstantiation = new (getASTContext()) MemberSpecializationInfo(RD, TSK); } @@ -1235,8 +1307,7 @@ void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) { } // Set access bits correctly on the directly-declared conversions. - for (UnresolvedSetIterator I = data().Conversions.begin(), - E = data().Conversions.end(); + for (conversion_iterator I = conversion_begin(), E = conversion_end(); I != E; ++I) I.setAccess((*I)->getAccess()); } @@ -1266,21 +1337,8 @@ bool CXXMethodDecl::isStatic() const { if (MD->getStorageClass() == SC_Static) return true; - DeclarationName Name = getDeclName(); - // [class.free]p1: - // Any allocation function for a class T is a static member - // (even if not explicitly declared static). - if (Name.getCXXOverloadedOperator() == OO_New || - Name.getCXXOverloadedOperator() == OO_Array_New) - return true; - - // [class.free]p6 Any deallocation function for a class X is a static member - // (even if not explicitly declared static). - if (Name.getCXXOverloadedOperator() == OO_Delete || - Name.getCXXOverloadedOperator() == OO_Array_Delete) - return true; - - return false; + OverloadedOperatorKind OOK = getDeclName().getCXXOverloadedOperator(); + return isStaticOverloadedOperator(OOK); } static bool recursivelyOverrides(const CXXMethodDecl *DerivedMD, @@ -1408,7 +1466,8 @@ bool CXXMethodDecl::isCopyAssignmentOperator() const { // type X, X&, const X&, volatile X& or const volatile X&. if (/*operator=*/getOverloadedOperator() != OO_Equal || /*non-static*/ isStatic() || - /*non-template*/getPrimaryTemplate() || getDescribedFunctionTemplate()) + /*non-template*/getPrimaryTemplate() || getDescribedFunctionTemplate() || + getNumParams() != 1) return false; QualType ParamType = getParamDecl(0)->getType(); @@ -1427,7 +1486,8 @@ bool CXXMethodDecl::isMoveAssignmentOperator() const { // 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()) + getPrimaryTemplate() || getDescribedFunctionTemplate() || + getNumParams() != 1) return false; QualType ParamType = getParamDecl(0)->getType(); @@ -1492,11 +1552,17 @@ bool CXXMethodDecl::hasInlineBody() const { } bool CXXMethodDecl::isLambdaStaticInvoker() const { - return getParent()->isLambda() && - getIdentifier() && getIdentifier()->getName() == "__invoke"; + const CXXRecordDecl *P = getParent(); + if (P->isLambda()) { + if (const CXXMethodDecl *StaticInvoker = P->getLambdaStaticInvoker()) { + if (StaticInvoker == this) return true; + if (P->isGenericLambda() && this->isFunctionTemplateSpecialization()) + return StaticInvoker == this->getPrimaryTemplate()->getTemplatedDecl(); + } + } + return false; } - CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo, bool IsVirtual, SourceLocation L, Expr *Init, @@ -1865,7 +1931,7 @@ NamespaceDecl::NamespaceDecl(DeclContext *DC, bool Inline, : NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace), LocStart(StartLoc), RBraceLoc(), AnonOrFirstNamespaceAndInline(0, Inline) { - setPreviousDeclaration(PrevDecl); + setPreviousDecl(PrevDecl); if (PrevDecl) AnonOrFirstNamespaceAndInline.setPointer(PrevDecl->getOriginalNamespace()); @@ -1959,8 +2025,8 @@ void UsingDecl::removeShadowDecl(UsingShadowDecl *S) { UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, - bool IsTypeNameArg) { - return new (C) UsingDecl(DC, UL, QualifierLoc, NameInfo, IsTypeNameArg); + bool HasTypename) { + return new (C) UsingDecl(DC, UL, QualifierLoc, NameInfo, HasTypename); } UsingDecl *UsingDecl::CreateDeserialized(ASTContext &C, unsigned ID) { @@ -1969,6 +2035,12 @@ UsingDecl *UsingDecl::CreateDeserialized(ASTContext &C, unsigned ID) { DeclarationNameInfo(), false); } +SourceRange UsingDecl::getSourceRange() const { + SourceLocation Begin = isAccessDeclaration() + ? getQualifierLoc().getBeginLoc() : UsingLocation; + return SourceRange(Begin, getNameInfo().getEndLoc()); +} + void UnresolvedUsingValueDecl::anchor() { } UnresolvedUsingValueDecl * @@ -1988,6 +2060,12 @@ UnresolvedUsingValueDecl::CreateDeserialized(ASTContext &C, unsigned ID) { DeclarationNameInfo()); } +SourceRange UnresolvedUsingValueDecl::getSourceRange() const { + SourceLocation Begin = isAccessDeclaration() + ? getQualifierLoc().getBeginLoc() : UsingLocation; + return SourceRange(Begin, getNameInfo().getEndLoc()); +} + void UnresolvedUsingTypenameDecl::anchor() { } UnresolvedUsingTypenameDecl * |