diff options
Diffstat (limited to 'clang/lib/AST')
43 files changed, 2286 insertions, 892 deletions
diff --git a/clang/lib/AST/ASTConcept.cpp b/clang/lib/AST/ASTConcept.cpp new file mode 100644 index 000000000000..fc32e768d92f --- /dev/null +++ b/clang/lib/AST/ASTConcept.cpp @@ -0,0 +1,55 @@ +//===--- ASTConcept.cpp - Concepts Related AST Data Structures --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file defines AST data structures related to concepts. +/// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ASTConcept.h" +#include "clang/AST/ASTContext.h" +using namespace clang; + +ASTConstraintSatisfaction::ASTConstraintSatisfaction(const ASTContext &C, + const ConstraintSatisfaction &Satisfaction): + NumRecords{Satisfaction.Details.size()}, + IsSatisfied{Satisfaction.IsSatisfied} { + for (unsigned I = 0; I < NumRecords; ++I) { + auto &Detail = Satisfaction.Details[I]; + if (Detail.second.is<Expr *>()) + new (getTrailingObjects<UnsatisfiedConstraintRecord>() + I) + UnsatisfiedConstraintRecord{Detail.first, + UnsatisfiedConstraintRecord::second_type( + Detail.second.get<Expr *>())}; + else { + auto &SubstitutionDiagnostic = + *Detail.second.get<std::pair<SourceLocation, StringRef> *>(); + unsigned MessageSize = SubstitutionDiagnostic.second.size(); + char *Mem = new (C) char[MessageSize]; + memcpy(Mem, SubstitutionDiagnostic.second.data(), MessageSize); + auto *NewSubstDiag = new (C) std::pair<SourceLocation, StringRef>( + SubstitutionDiagnostic.first, StringRef(Mem, MessageSize)); + new (getTrailingObjects<UnsatisfiedConstraintRecord>() + I) + UnsatisfiedConstraintRecord{Detail.first, + UnsatisfiedConstraintRecord::second_type( + NewSubstDiag)}; + } + } +} + + +ASTConstraintSatisfaction * +ASTConstraintSatisfaction::Create(const ASTContext &C, + const ConstraintSatisfaction &Satisfaction) { + std::size_t size = + totalSizeToAlloc<UnsatisfiedConstraintRecord>( + Satisfaction.Details.size()); + void *Mem = C.Allocate(size, alignof(ASTConstraintSatisfaction)); + return new (Mem) ASTConstraintSatisfaction(C, Satisfaction); +} diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index cda51ec755a8..a51429264dbe 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -14,6 +14,7 @@ #include "CXXABI.h" #include "Interp/Context.h" #include "clang/AST/APValue.h" +#include "clang/AST/ASTConcept.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Attr.h" @@ -98,6 +99,32 @@ using namespace clang; enum FloatingRank { Float16Rank, HalfRank, FloatRank, DoubleRank, LongDoubleRank, Float128Rank }; +const Expr *ASTContext::traverseIgnored(const Expr *E) const { + return traverseIgnored(const_cast<Expr *>(E)); +} + +Expr *ASTContext::traverseIgnored(Expr *E) const { + if (!E) + return nullptr; + + switch (Traversal) { + case ast_type_traits::TK_AsIs: + return E; + case ast_type_traits::TK_IgnoreImplicitCastsAndParentheses: + return E->IgnoreParenImpCasts(); + case ast_type_traits::TK_IgnoreUnlessSpelledInSource: + return E->IgnoreUnlessSpelledInSource(); + } + llvm_unreachable("Invalid Traversal type!"); +} + +ast_type_traits::DynTypedNode +ASTContext::traverseIgnored(const ast_type_traits::DynTypedNode &N) const { + if (const auto *E = N.get<Expr>()) { + return ast_type_traits::DynTypedNode::create(*traverseIgnored(E)); + } + return N; +} /// \returns location that is relevant when searching for Doc comments related /// to \p D. @@ -163,7 +190,9 @@ static SourceLocation getDeclLocForCommentSearch(const Decl *D, if (isa<ObjCMethodDecl>(D) || isa<ObjCContainerDecl>(D) || isa<ObjCPropertyDecl>(D) || isa<RedeclarableTemplateDecl>(D) || - isa<ClassTemplateSpecializationDecl>(D)) + isa<ClassTemplateSpecializationDecl>(D) || + // Allow association with Y across {} in `typedef struct X {} Y`. + isa<TypedefDecl>(D)) return D->getBeginLoc(); else { const SourceLocation DeclLoc = D->getLocation(); @@ -632,8 +661,9 @@ comments::FullComment *ASTContext::getCommentForDecl( return FC; } -void +void ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID, + const ASTContext &C, TemplateTemplateParmDecl *Parm) { ID.AddInteger(Parm->getDepth()); ID.AddInteger(Parm->getPosition()); @@ -647,6 +677,16 @@ ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID, if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) { ID.AddInteger(0); ID.AddBoolean(TTP->isParameterPack()); + const TypeConstraint *TC = TTP->getTypeConstraint(); + ID.AddBoolean(TC != nullptr); + if (TC) + TC->getImmediatelyDeclaredConstraint()->Profile(ID, C, + /*Canonical=*/true); + if (TTP->isExpandedParameterPack()) { + ID.AddBoolean(true); + ID.AddInteger(TTP->getNumExpansionParameters()); + } else + ID.AddBoolean(false); continue; } @@ -668,8 +708,12 @@ ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID, auto *TTP = cast<TemplateTemplateParmDecl>(*P); ID.AddInteger(2); - Profile(ID, TTP); + Profile(ID, C, TTP); } + Expr *RequiresClause = Parm->getTemplateParameters()->getRequiresClause(); + ID.AddBoolean(RequiresClause != nullptr); + if (RequiresClause) + RequiresClause->Profile(ID, C, /*Canonical=*/true); } TemplateTemplateParmDecl * @@ -677,7 +721,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( TemplateTemplateParmDecl *TTP) const { // Check if we already have a canonical template template parameter. llvm::FoldingSetNodeID ID; - CanonicalTemplateTemplateParm::Profile(ID, TTP); + CanonicalTemplateTemplateParm::Profile(ID, *this, TTP); void *InsertPos = nullptr; CanonicalTemplateTemplateParm *Canonical = CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos); @@ -691,15 +735,79 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( for (TemplateParameterList::const_iterator P = Params->begin(), PEnd = Params->end(); P != PEnd; ++P) { - if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) - CanonParams.push_back( - TemplateTypeParmDecl::Create(*this, getTranslationUnitDecl(), - SourceLocation(), - SourceLocation(), - TTP->getDepth(), - TTP->getIndex(), nullptr, false, - TTP->isParameterPack())); - else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) { + if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) { + TemplateTypeParmDecl *NewTTP = TemplateTypeParmDecl::Create(*this, + getTranslationUnitDecl(), SourceLocation(), SourceLocation(), + TTP->getDepth(), TTP->getIndex(), nullptr, false, + TTP->isParameterPack(), TTP->hasTypeConstraint(), + TTP->isExpandedParameterPack() ? + llvm::Optional<unsigned>(TTP->getNumExpansionParameters()) : None); + if (const auto *TC = TTP->getTypeConstraint()) { + // This is a bit ugly - we need to form a new immediately-declared + // constraint that references the new parameter; this would ideally + // require semantic analysis (e.g. template<C T> struct S {}; - the + // converted arguments of C<T> could be an argument pack if C is + // declared as template<typename... T> concept C = ...). + // We don't have semantic analysis here so we dig deep into the + // ready-made constraint expr and change the thing manually. + Expr *IDC = TC->getImmediatelyDeclaredConstraint(); + ConceptSpecializationExpr *CSE; + if (const auto *Fold = dyn_cast<CXXFoldExpr>(IDC)) + CSE = cast<ConceptSpecializationExpr>(Fold->getLHS()); + else + CSE = cast<ConceptSpecializationExpr>(IDC); + ArrayRef<TemplateArgument> OldConverted = CSE->getTemplateArguments(); + SmallVector<TemplateArgument, 3> NewConverted; + NewConverted.reserve(OldConverted.size()); + + QualType ParamAsArgument(NewTTP->getTypeForDecl(), 0); + if (OldConverted.front().getKind() == TemplateArgument::Pack) { + // The case: + // template<typename... T> concept C = true; + // template<C<int> T> struct S; -> constraint is C<{T, int}> + NewConverted.push_back(ParamAsArgument); + for (auto &Arg : OldConverted.front().pack_elements().drop_front(1)) + NewConverted.push_back(Arg); + TemplateArgument NewPack(NewConverted); + + NewConverted.clear(); + NewConverted.push_back(NewPack); + assert(OldConverted.size() == 1 && + "Template parameter pack should be the last parameter"); + } else { + assert(OldConverted.front().getKind() == TemplateArgument::Type && + "Unexpected first argument kind for immediately-declared " + "constraint"); + NewConverted.push_back(ParamAsArgument); + for (auto &Arg : OldConverted.drop_front(1)) + NewConverted.push_back(Arg); + } + Expr *NewIDC = ConceptSpecializationExpr::Create(*this, + NestedNameSpecifierLoc(), /*TemplateKWLoc=*/SourceLocation(), + CSE->getConceptNameInfo(), /*FoundDecl=*/CSE->getNamedConcept(), + CSE->getNamedConcept(), + // Actually canonicalizing a TemplateArgumentLoc is difficult so we + // simply omit the ArgsAsWritten + /*ArgsAsWritten=*/nullptr, NewConverted, nullptr); + + if (auto *OrigFold = dyn_cast<CXXFoldExpr>(IDC)) + NewIDC = new (*this) CXXFoldExpr(OrigFold->getType(), + SourceLocation(), NewIDC, + BinaryOperatorKind::BO_LAnd, + SourceLocation(), /*RHS=*/nullptr, + SourceLocation(), + /*NumExpansions=*/None); + + NewTTP->setTypeConstraint( + NestedNameSpecifierLoc(), + DeclarationNameInfo(TC->getNamedConcept()->getDeclName(), + SourceLocation()), /*FoundDecl=*/nullptr, + // Actually canonicalizing a TemplateArgumentLoc is difficult so we + // simply omit the ArgsAsWritten + CSE->getNamedConcept(), /*ArgsAsWritten=*/nullptr, NewIDC); + } + CanonParams.push_back(NewTTP); + } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) { QualType T = getCanonicalType(NTTP->getType()); TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(T); NonTypeTemplateParmDecl *Param; @@ -738,9 +846,9 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( cast<TemplateTemplateParmDecl>(*P))); } - assert(!TTP->getTemplateParameters()->getRequiresClause() && - "Unexpected requires-clause on template template-parameter"); - Expr *const CanonRequiresClause = nullptr; + Expr *CanonRequiresClause = nullptr; + if (Expr *RequiresClause = TTP->getTemplateParameters()->getRequiresClause()) + CanonRequiresClause = RequiresClause; TemplateTemplateParmDecl *CanonTTP = TemplateTemplateParmDecl::Create(*this, getTranslationUnitDecl(), @@ -769,6 +877,7 @@ CXXABI *ASTContext::createCXXABI(const TargetInfo &T) { if (!LangOpts.CPlusPlus) return nullptr; switch (T.getCXXABI().getKind()) { + case TargetCXXABI::Fuchsia: case TargetCXXABI::GenericARM: // Same as Itanium at this level case TargetCXXABI::iOS: case TargetCXXABI::iOS64: @@ -797,15 +906,18 @@ static const LangASMap *getAddressSpaceMap(const TargetInfo &T, // The fake address space map must have a distinct entry for each // language-specific address space. static const unsigned FakeAddrSpaceMap[] = { - 0, // Default - 1, // opencl_global - 3, // opencl_local - 2, // opencl_constant - 0, // opencl_private - 4, // opencl_generic - 5, // cuda_device - 6, // cuda_constant - 7 // cuda_shared + 0, // Default + 1, // opencl_global + 3, // opencl_local + 2, // opencl_constant + 0, // opencl_private + 4, // opencl_generic + 5, // cuda_device + 6, // cuda_constant + 7, // cuda_shared + 8, // ptr32_sptr + 9, // ptr32_uptr + 10 // ptr64 }; return &FakeAddrSpaceMap; } else { @@ -832,7 +944,8 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, : ConstantArrayTypes(this_()), FunctionProtoTypes(this_()), TemplateSpecializationTypes(this_()), DependentTemplateSpecializationTypes(this_()), - SubstTemplateTemplateParmPacks(this_()), SourceMgr(SM), LangOpts(LOpts), + SubstTemplateTemplateParmPacks(this_()), + CanonTemplateTemplateParms(this_()), SourceMgr(SM), LangOpts(LOpts), SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)), XRayFilter(new XRayFunctionFilter(LangOpts.XRayAlwaysInstrumentFiles, LangOpts.XRayNeverInstrumentFiles, @@ -875,10 +988,6 @@ ASTContext::~ASTContext() { A != AEnd; ++A) A->second->~AttrVec(); - for (std::pair<const MaterializeTemporaryExpr *, APValue *> &MTVPair : - MaterializedTemporaryValues) - MTVPair.second->~APValue(); - for (const auto &Value : ModuleInitializers) Value.second->~PerModuleInitializers(); @@ -895,15 +1004,15 @@ class ASTContext::ParentMap { /// only storing a unique pointer to them. using ParentMapPointers = llvm::DenseMap< const void *, - llvm::PointerUnion4<const Decl *, const Stmt *, - ast_type_traits::DynTypedNode *, ParentVector *>>; + llvm::PointerUnion<const Decl *, const Stmt *, + ast_type_traits::DynTypedNode *, ParentVector *>>; /// Parent map for nodes without pointer identity. We store a full /// DynTypedNode for all keys. using ParentMapOtherNodes = llvm::DenseMap< ast_type_traits::DynTypedNode, - llvm::PointerUnion4<const Decl *, const Stmt *, - ast_type_traits::DynTypedNode *, ParentVector *>>; + llvm::PointerUnion<const Decl *, const Stmt *, + ast_type_traits::DynTypedNode *, ParentVector *>>; ParentMapPointers PointerParents; ParentMapOtherNodes OtherParents; @@ -959,7 +1068,7 @@ public: void ASTContext::setTraversalScope(const std::vector<Decl *> &TopLevelDecls) { TraversalScope = TopLevelDecls; - Parents.reset(); + Parents.clear(); } void ASTContext::AddDeallocation(void (*Callback)(void *), void *Data) const { @@ -2438,7 +2547,7 @@ structHasUniqueObjectRepresentations(const ASTContext &Context, return llvm::None; SmallVector<std::pair<QualType, int64_t>, 4> Bases; - for (const auto Base : ClassDecl->bases()) { + for (const auto &Base : ClassDecl->bases()) { // Empty types can be inherited from, and non-empty types can potentially // have tail padding, so just make sure there isn't an error. if (!isStructEmpty(Base.getType())) { @@ -2456,7 +2565,7 @@ structHasUniqueObjectRepresentations(const ASTContext &Context, Layout.getBaseClassOffset(R.first->getAsCXXRecordDecl()); }); - for (const auto Base : Bases) { + for (const auto &Base : Bases) { int64_t BaseOffset = Context.toBits( Layout.getBaseClassOffset(Base.first->getAsCXXRecordDecl())); int64_t BaseSize = Base.second; @@ -2654,8 +2763,7 @@ const ObjCInterfaceDecl *ASTContext::getObjContainingInterface( /// Get the copy initialization expression of VarDecl, or nullptr if /// none exists. -ASTContext::BlockVarCopyInit -ASTContext::getBlockVarCopyInit(const VarDecl*VD) const { +BlockVarCopyInit ASTContext::getBlockVarCopyInit(const VarDecl *VD) const { assert(VD && "Passed null params"); assert(VD->hasAttr<BlocksAttr>() && "getBlockVarCopyInits - not __block var"); @@ -2809,6 +2917,16 @@ QualType ASTContext::getObjCGCQualType(QualType T, return getExtQualType(TypeNode, Quals); } +QualType ASTContext::removePtrSizeAddrSpace(QualType T) const { + if (const PointerType *Ptr = T->getAs<PointerType>()) { + QualType Pointee = Ptr->getPointeeType(); + if (isPtrSizeAddressSpace(Pointee.getAddressSpace())) { + return getPointerType(removeAddrSpaceQualType(Pointee)); + } + } + return T; +} + const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T, FunctionType::ExtInfo Info) { if (T->getExtInfo() == Info) @@ -2883,6 +3001,29 @@ bool ASTContext::hasSameFunctionTypeIgnoringExceptionSpec(QualType T, getFunctionTypeWithExceptionSpec(U, EST_None))); } +QualType ASTContext::getFunctionTypeWithoutPtrSizes(QualType T) { + if (const auto *Proto = T->getAs<FunctionProtoType>()) { + QualType RetTy = removePtrSizeAddrSpace(Proto->getReturnType()); + SmallVector<QualType, 16> Args(Proto->param_types()); + for (unsigned i = 0, n = Args.size(); i != n; ++i) + Args[i] = removePtrSizeAddrSpace(Args[i]); + return getFunctionType(RetTy, Args, Proto->getExtProtoInfo()); + } + + if (const FunctionNoProtoType *Proto = T->getAs<FunctionNoProtoType>()) { + QualType RetTy = removePtrSizeAddrSpace(Proto->getReturnType()); + return getFunctionNoProtoType(RetTy, Proto->getExtInfo()); + } + + return T; +} + +bool ASTContext::hasSameFunctionTypeIgnoringPtrSizes(QualType T, QualType U) { + return hasSameType(T, U) || + hasSameType(getFunctionTypeWithoutPtrSizes(T), + getFunctionTypeWithoutPtrSizes(U)); +} + void ASTContext::adjustExceptionSpec( FunctionDecl *FD, const FunctionProtoType::ExceptionSpecInfo &ESI, bool AsWritten) { @@ -3547,10 +3688,10 @@ ASTContext::getDependentVectorType(QualType VecType, Expr *SizeExpr, (void)CanonCheck; DependentVectorTypes.InsertNode(New, InsertPos); } else { - QualType Canon = getDependentSizedExtVectorType(CanonVecTy, SizeExpr, - SourceLocation()); + QualType CanonExtTy = getDependentSizedExtVectorType(CanonVecTy, SizeExpr, + SourceLocation()); New = new (*this, TypeAlignment) DependentVectorType( - *this, VecType, Canon, SizeExpr, AttrLoc, VecKind); + *this, VecType, CanonExtTy, SizeExpr, AttrLoc, VecKind); } } @@ -3620,10 +3761,10 @@ ASTContext::getDependentSizedExtVectorType(QualType vecType, (void)CanonCheck; DependentSizedExtVectorTypes.InsertNode(New, InsertPos); } else { - QualType Canon = getDependentSizedExtVectorType(CanonVecTy, SizeExpr, - SourceLocation()); - New = new (*this, TypeAlignment) - DependentSizedExtVectorType(*this, vecType, Canon, SizeExpr, AttrLoc); + QualType CanonExtTy = getDependentSizedExtVectorType(CanonVecTy, SizeExpr, + SourceLocation()); + New = new (*this, TypeAlignment) DependentSizedExtVectorType( + *this, vecType, CanonExtTy, SizeExpr, AttrLoc); } } @@ -3877,10 +4018,11 @@ QualType ASTContext::getFunctionTypeInternal( auto ESH = FunctionProtoType::getExceptionSpecSize( EPI.ExceptionSpec.Type, EPI.ExceptionSpec.Exceptions.size()); size_t Size = FunctionProtoType::totalSizeToAlloc< - QualType, FunctionType::FunctionTypeExtraBitfields, + QualType, SourceLocation, FunctionType::FunctionTypeExtraBitfields, FunctionType::ExceptionType, Expr *, FunctionDecl *, FunctionProtoType::ExtParameterInfo, Qualifiers>( - NumArgs, FunctionProtoType::hasExtraBitfields(EPI.ExceptionSpec.Type), + NumArgs, EPI.Variadic, + FunctionProtoType::hasExtraBitfields(EPI.ExceptionSpec.Type), ESH.NumExceptionType, ESH.NumExprPtr, ESH.NumFunctionDeclPtr, EPI.ExtParameterInfos ? NumArgs : 0, EPI.TypeQuals.hasNonFastQualifiers() ? 1 : 0); @@ -6813,21 +6955,19 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S, S += ObjCEncodingForEnumType(this, cast<EnumType>(CT)); return; - case Type::Complex: { - const auto *CT = T->castAs<ComplexType>(); + case Type::Complex: S += 'j'; - getObjCEncodingForTypeImpl(CT->getElementType(), S, ObjCEncOptions(), + getObjCEncodingForTypeImpl(T->castAs<ComplexType>()->getElementType(), S, + ObjCEncOptions(), /*Field=*/nullptr); return; - } - case Type::Atomic: { - const auto *AT = T->castAs<AtomicType>(); + case Type::Atomic: S += 'A'; - getObjCEncodingForTypeImpl(AT->getValueType(), S, ObjCEncOptions(), + getObjCEncodingForTypeImpl(T->castAs<AtomicType>()->getValueType(), S, + ObjCEncOptions(), /*Field=*/nullptr); return; - } // encoding for pointer or reference types. case Type::Pointer: @@ -8645,8 +8785,8 @@ QualType ASTContext::mergeFunctionParameterTypes(QualType lhs, QualType rhs, QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, bool OfBlockPointer, bool Unqualified) { - const auto *lbase = lhs->getAs<FunctionType>(); - const auto *rbase = rhs->getAs<FunctionType>(); + const auto *lbase = lhs->castAs<FunctionType>(); + const auto *rbase = rhs->castAs<FunctionType>(); const auto *lproto = dyn_cast<FunctionProtoType>(lbase); const auto *rproto = dyn_cast<FunctionProtoType>(rbase); bool allLTypes = true; @@ -10170,6 +10310,7 @@ MangleContext *ASTContext::createMangleContext(const TargetInfo *T) { if (!T) T = Target; switch (T->getCXXABI().getKind()) { + case TargetCXXABI::Fuchsia: case TargetCXXABI::GenericAArch64: case TargetCXXABI::GenericItanium: case TargetCXXABI::GenericARM: @@ -10324,21 +10465,6 @@ unsigned ASTContext::getParameterIndex(const ParmVarDecl *D) const { return I->second; } -APValue * -ASTContext::getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E, - bool MayCreate) { - assert(E && E->getStorageDuration() == SD_Static && - "don't need to cache the computed value for this temporary"); - if (MayCreate) { - APValue *&MTVI = MaterializedTemporaryValues[E]; - if (!MTVI) - MTVI = new (*this) APValue; - return MTVI; - } - - return MaterializedTemporaryValues.lookup(E); -} - QualType ASTContext::getStringLiteralArrayType(QualType EltTy, unsigned Length) const { // A C++ string literal has a const-qualified element type (C++ 2.13.4p1). @@ -10410,7 +10536,8 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) { class ASTContext::ParentMap::ASTVisitor : public RecursiveASTVisitor<ASTVisitor> { public: - ASTVisitor(ParentMap &Map) : Map(Map) {} + ASTVisitor(ParentMap &Map, ASTContext &Context) + : Map(Map), Context(Context) {} private: friend class RecursiveASTVisitor<ASTVisitor>; @@ -10480,9 +10607,12 @@ private: } bool TraverseStmt(Stmt *StmtNode) { - return TraverseNode( - StmtNode, StmtNode, [&] { return VisitorBase::TraverseStmt(StmtNode); }, - &Map.PointerParents); + Stmt *FilteredNode = StmtNode; + if (auto *ExprNode = dyn_cast_or_null<Expr>(FilteredNode)) + FilteredNode = Context.traverseIgnored(ExprNode); + return TraverseNode(FilteredNode, FilteredNode, + [&] { return VisitorBase::TraverseStmt(FilteredNode); }, + &Map.PointerParents); } bool TraverseTypeLoc(TypeLoc TypeLocNode) { @@ -10500,20 +10630,22 @@ private: } ParentMap ⤅ + ASTContext &Context; llvm::SmallVector<ast_type_traits::DynTypedNode, 16> ParentStack; }; ASTContext::ParentMap::ParentMap(ASTContext &Ctx) { - ASTVisitor(*this).TraverseAST(Ctx); + ASTVisitor(*this, Ctx).TraverseAST(Ctx); } ASTContext::DynTypedNodeList ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) { - if (!Parents) + std::unique_ptr<ParentMap> &P = Parents[Traversal]; + if (!P) // We build the parent map for the traversal scope (usually whole TU), as // hasAncestor can escape any subtree. - Parents = std::make_unique<ParentMap>(*this); - return Parents->getParents(Node); + P = std::make_unique<ParentMap>(*this); + return P->getParents(Node); } bool @@ -10763,3 +10895,66 @@ QualType ASTContext::getCorrespondingSignedFixedPointType(QualType Ty) const { llvm_unreachable("Unexpected unsigned fixed point type"); } } + +ParsedTargetAttr +ASTContext::filterFunctionTargetAttrs(const TargetAttr *TD) const { + assert(TD != nullptr); + ParsedTargetAttr ParsedAttr = TD->parse(); + + ParsedAttr.Features.erase( + llvm::remove_if(ParsedAttr.Features, + [&](const std::string &Feat) { + return !Target->isValidFeatureName( + StringRef{Feat}.substr(1)); + }), + ParsedAttr.Features.end()); + return ParsedAttr; +} + +void ASTContext::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap, + const FunctionDecl *FD) const { + if (FD) + getFunctionFeatureMap(FeatureMap, GlobalDecl().getWithDecl(FD)); + else + Target->initFeatureMap(FeatureMap, getDiagnostics(), + Target->getTargetOpts().CPU, + Target->getTargetOpts().Features); +} + +// Fills in the supplied string map with the set of target features for the +// passed in function. +void ASTContext::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap, + GlobalDecl GD) const { + StringRef TargetCPU = Target->getTargetOpts().CPU; + const FunctionDecl *FD = GD.getDecl()->getAsFunction(); + if (const auto *TD = FD->getAttr<TargetAttr>()) { + ParsedTargetAttr ParsedAttr = filterFunctionTargetAttrs(TD); + + // Make a copy of the features as passed on the command line into the + // beginning of the additional features from the function to override. + ParsedAttr.Features.insert( + ParsedAttr.Features.begin(), + Target->getTargetOpts().FeaturesAsWritten.begin(), + Target->getTargetOpts().FeaturesAsWritten.end()); + + if (ParsedAttr.Architecture != "" && + Target->isValidCPUName(ParsedAttr.Architecture)) + TargetCPU = ParsedAttr.Architecture; + + // Now populate the feature map, first with the TargetCPU which is either + // the default or a new one from the target attribute string. Then we'll use + // the passed in features (FeaturesAsWritten) along with the new ones from + // the attribute. + Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, + ParsedAttr.Features); + } else if (const auto *SD = FD->getAttr<CPUSpecificAttr>()) { + llvm::SmallVector<StringRef, 32> FeaturesTmp; + Target->getCPUSpecificCPUDispatchFeatures( + SD->getCPUName(GD.getMultiVersionIndex())->getName(), FeaturesTmp); + std::vector<std::string> Features(FeaturesTmp.begin(), FeaturesTmp.end()); + Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features); + } else { + Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, + Target->getTargetOpts().Features); + } +} diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp index 30985441031d..ea4d0dea58a3 100644 --- a/clang/lib/AST/ASTDiagnostic.cpp +++ b/clang/lib/AST/ASTDiagnostic.cpp @@ -300,8 +300,7 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, // Give some additional info on vector types. These are either not desugared // or displaying complex __attribute__ expressions so add details of the // type and element count. - if (Ty->isVectorType()) { - const VectorType *VTy = Ty->getAs<VectorType>(); + if (const auto *VTy = Ty->getAs<VectorType>()) { std::string DecoratedString; llvm::raw_string_ostream OS(DecoratedString); const char *Values = VTy->getNumElements() > 1 ? "values" : "value"; @@ -338,6 +337,21 @@ void clang::FormatASTNodeDiagnosticArgument( switch (Kind) { default: llvm_unreachable("unknown ArgumentKind"); + case DiagnosticsEngine::ak_addrspace: { + assert(Modifier.empty() && Argument.empty() && + "Invalid modifier for Qualfiers argument"); + + auto S = Qualifiers::getAddrSpaceAsString(static_cast<LangAS>(Val)); + if (S.empty()) { + OS << (Context.getLangOpts().OpenCL ? "default" : "generic"); + OS << " address space"; + } else { + OS << "address space"; + OS << " '" << S << "'"; + } + NeedQuotes = false; + break; + } case DiagnosticsEngine::ak_qual: { assert(Modifier.empty() && Argument.empty() && "Invalid modifier for Qualfiers argument"); @@ -348,7 +362,7 @@ void clang::FormatASTNodeDiagnosticArgument( OS << "unqualified"; NeedQuotes = false; } else { - OS << Q.getAsString(); + OS << S; } break; } @@ -589,8 +603,7 @@ class TemplateDiff { unsigned ReadNode; public: - DiffTree() : - CurrentNode(0), NextFreeNode(1) { + DiffTree() : CurrentNode(0), NextFreeNode(1), ReadNode(0) { FlatTree.push_back(DiffNode()); } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 54acca7dc62c..22fb67478c96 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -44,6 +44,7 @@ #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeVisitor.h" #include "clang/AST/UnresolvedSet.h" +#include "clang/Basic/Builtins.h" #include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/IdentifierTable.h" @@ -297,6 +298,48 @@ namespace clang { return nullptr; } + void addDeclToContexts(Decl *FromD, Decl *ToD) { + if (Importer.isMinimalImport()) { + // In minimal import case the decl must be added even if it is not + // contained in original context, for LLDB compatibility. + // FIXME: Check if a better solution is possible. + if (!FromD->getDescribedTemplate() && + FromD->getFriendObjectKind() == Decl::FOK_None) + ToD->getLexicalDeclContext()->addDeclInternal(ToD); + return; + } + + DeclContext *FromDC = FromD->getDeclContext(); + DeclContext *FromLexicalDC = FromD->getLexicalDeclContext(); + DeclContext *ToDC = ToD->getDeclContext(); + DeclContext *ToLexicalDC = ToD->getLexicalDeclContext(); + + bool Visible = false; + if (FromDC->containsDeclAndLoad(FromD)) { + ToDC->addDeclInternal(ToD); + Visible = true; + } + if (ToDC != ToLexicalDC && FromLexicalDC->containsDeclAndLoad(FromD)) { + ToLexicalDC->addDeclInternal(ToD); + Visible = true; + } + + // If the Decl was added to any context, it was made already visible. + // Otherwise it is still possible that it should be visible. + if (!Visible) { + if (auto *FromNamed = dyn_cast<NamedDecl>(FromD)) { + auto *ToNamed = cast<NamedDecl>(ToD); + DeclContextLookupResult FromLookup = + FromDC->lookup(FromNamed->getDeclName()); + for (NamedDecl *ND : FromLookup) + if (ND == FromNamed) { + ToDC->makeDeclVisibleInContext(ToNamed); + break; + } + } + } + } + public: explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) {} @@ -483,6 +526,9 @@ namespace clang { ExpectedDecl VisitUsingDirectiveDecl(UsingDirectiveDecl *D); ExpectedDecl VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); ExpectedDecl VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); + ExpectedDecl VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D); + ExpectedDecl + VisitLifetimeExtendedTemporaryDecl(LifetimeExtendedTemporaryDecl *D); Expected<ObjCTypeParamList *> ImportObjCTypeParamList(ObjCTypeParamList *list); @@ -644,6 +690,11 @@ namespace clang { Expected<FunctionDecl *> FindFunctionTemplateSpecialization( FunctionDecl *FromFD); + + // Returns true if the given function has a placeholder return type and + // that type is declared inside the body of the function. + // E.g. auto f() { struct X{}; return X(); } + bool hasAutoReturnTypeDeclaredInside(FunctionDecl *D); }; template <typename InContainerTy> @@ -1543,6 +1594,10 @@ Error ASTNodeImporter::ImportDeclParts( DeclarationName &Name, NamedDecl *&ToD, SourceLocation &Loc) { // Check if RecordDecl is in FunctionDecl parameters to avoid infinite loop. // example: int struct_in_proto(struct data_t{int a;int b;} *d); + // FIXME: We could support these constructs by importing a different type of + // this parameter and by importing the original type of the parameter only + // after the FunctionDecl is created. See + // VisitFunctionDecl::UsedDifferentProtoType. DeclContext *OrigDC = D->getDeclContext(); FunctionDecl *FunDecl; if (isa<RecordDecl>(D) && (FunDecl = dyn_cast<FunctionDecl>(OrigDC)) && @@ -1679,7 +1734,34 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { Error ChildErrors = Error::success(); for (auto *From : FromDC->decls()) { ExpectedDecl ImportedOrErr = import(From); - if (!ImportedOrErr) { + + // If we are in the process of ImportDefinition(...) for a RecordDecl we + // want to make sure that we are also completing each FieldDecl. There + // are currently cases where this does not happen and this is correctness + // fix since operations such as code generation will expect this to be so. + if (ImportedOrErr) { + FieldDecl *FieldFrom = dyn_cast_or_null<FieldDecl>(From); + Decl *ImportedDecl = (Decl*)*ImportedOrErr; + FieldDecl *FieldTo = dyn_cast_or_null<FieldDecl>(ImportedDecl); + if (FieldFrom && FieldTo) { + const RecordType *RecordFrom = FieldFrom->getType()->getAs<RecordType>(); + const RecordType *RecordTo = FieldTo->getType()->getAs<RecordType>(); + if (RecordFrom && RecordTo) { + RecordDecl *FromRecordDecl = RecordFrom->getDecl(); + RecordDecl *ToRecordDecl = RecordTo->getDecl(); + + if (FromRecordDecl->isCompleteDefinition() && + !ToRecordDecl->isCompleteDefinition()) { + Error Err = ImportDefinition(FromRecordDecl, ToRecordDecl); + + if (Err && AccumulateChildErrors) + ChildErrors = joinErrors(std::move(ChildErrors), std::move(Err)); + else + consumeError(std::move(Err)); + } + } + } + } else { if (AccumulateChildErrors) ChildErrors = joinErrors(std::move(ChildErrors), ImportedOrErr.takeError()); @@ -2224,6 +2306,9 @@ ExpectedDecl ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc()); if (!BeginLocOrErr) return BeginLocOrErr.takeError(); + ExpectedSLoc RBraceLocOrErr = import(D->getRBraceLoc()); + if (!RBraceLocOrErr) + return RBraceLocOrErr.takeError(); // Create the "to" namespace, if needed. NamespaceDecl *ToNamespace = MergeWithNamespace; @@ -2233,6 +2318,7 @@ ExpectedDecl ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { *BeginLocOrErr, Loc, Name.getAsIdentifierInfo(), /*PrevDecl=*/nullptr)) return ToNamespace; + ToNamespace->setRBraceLoc(*RBraceLocOrErr); ToNamespace->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToNamespace); @@ -2541,9 +2627,10 @@ ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { SourceLocation ToBeginLoc; NestedNameSpecifierLoc ToQualifierLoc; QualType ToIntegerType; - if (auto Imp = importSeq( - D->getBeginLoc(), D->getQualifierLoc(), D->getIntegerType())) - std::tie(ToBeginLoc, ToQualifierLoc, ToIntegerType) = *Imp; + SourceRange ToBraceRange; + if (auto Imp = importSeq(D->getBeginLoc(), D->getQualifierLoc(), + D->getIntegerType(), D->getBraceRange())) + std::tie(ToBeginLoc, ToQualifierLoc, ToIntegerType, ToBraceRange) = *Imp; else return Imp.takeError(); @@ -2557,6 +2644,7 @@ ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { D2->setQualifierInfo(ToQualifierLoc); D2->setIntegerType(ToIntegerType); + D2->setBraceRange(ToBraceRange); D2->setAccess(D->getAccess()); D2->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(D2); @@ -2718,11 +2806,7 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { D2 = D2CXX; D2->setAccess(D->getAccess()); D2->setLexicalDeclContext(LexicalDC); - if (!DCXX->getDescribedClassTemplate() || DCXX->isImplicit()) - LexicalDC->addDeclInternal(D2); - - if (LexicalDC != DC && D->isInIdentifierNamespace(Decl::IDNS_TagFriend)) - DC->makeDeclVisibleInContext(D2); + addDeclToContexts(D, D2); if (ClassTemplateDecl *FromDescribed = DCXX->getDescribedClassTemplate()) { @@ -2788,9 +2872,13 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { Name.getAsIdentifierInfo(), PrevDecl)) return D2; D2->setLexicalDeclContext(LexicalDC); - LexicalDC->addDeclInternal(D2); + addDeclToContexts(D, D2); } + if (auto BraceRangeOrErr = import(D->getBraceRange())) + D2->setBraceRange(*BraceRangeOrErr); + else + return BraceRangeOrErr.takeError(); if (auto QualifierLocOrErr = import(D->getQualifierLoc())) D2->setQualifierInfo(*QualifierLocOrErr); else @@ -2991,6 +3079,46 @@ Error ASTNodeImporter::ImportFunctionDeclBody(FunctionDecl *FromFD, return Error::success(); } +// Returns true if the given D has a DeclContext up to the TranslationUnitDecl +// which is equal to the given DC. +static bool isAncestorDeclContextOf(const DeclContext *DC, const Decl *D) { + const DeclContext *DCi = D->getDeclContext(); + while (DCi != D->getTranslationUnitDecl()) { + if (DCi == DC) + return true; + DCi = DCi->getParent(); + } + return false; +} + +bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) { + QualType FromTy = D->getType(); + const FunctionProtoType *FromFPT = FromTy->getAs<FunctionProtoType>(); + assert(FromFPT && "Must be called on FunctionProtoType"); + if (AutoType *AutoT = FromFPT->getReturnType()->getContainedAutoType()) { + QualType DeducedT = AutoT->getDeducedType(); + if (const RecordType *RecordT = + DeducedT.isNull() ? nullptr : dyn_cast<RecordType>(DeducedT)) { + RecordDecl *RD = RecordT->getDecl(); + assert(RD); + if (isAncestorDeclContextOf(D, RD)) { + assert(RD->getLexicalDeclContext() == RD->getDeclContext()); + return true; + } + } + } + if (const TypedefType *TypedefT = + dyn_cast<TypedefType>(FromFPT->getReturnType())) { + TypedefNameDecl *TD = TypedefT->getDecl(); + assert(TD); + if (isAncestorDeclContextOf(D, TD)) { + assert(TD->getLexicalDeclContext() == TD->getDeclContext()); + return true; + } + } + return false; +} + ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { SmallVector<Decl *, 2> Redecls = getCanonicalForwardRedeclChain(D); @@ -3114,32 +3242,49 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { return std::move(Err); QualType FromTy = D->getType(); - bool usedDifferentExceptionSpec = false; - - if (const auto *FromFPT = D->getType()->getAs<FunctionProtoType>()) { + // Set to true if we do not import the type of the function as is. There are + // cases when the original type would result in an infinite recursion during + // the import. To avoid an infinite recursion when importing, we create the + // FunctionDecl with a simplified function type and update it only after the + // relevant AST nodes are already imported. + bool UsedDifferentProtoType = false; + if (const auto *FromFPT = FromTy->getAs<FunctionProtoType>()) { + QualType FromReturnTy = FromFPT->getReturnType(); + // Functions with auto return type may define a struct inside their body + // and the return type could refer to that struct. + // E.g.: auto foo() { struct X{}; return X(); } + // To avoid an infinite recursion when importing, create the FunctionDecl + // with a simplified return type. + if (hasAutoReturnTypeDeclaredInside(D)) { + FromReturnTy = Importer.getFromContext().VoidTy; + UsedDifferentProtoType = true; + } FunctionProtoType::ExtProtoInfo FromEPI = FromFPT->getExtProtoInfo(); // FunctionProtoType::ExtProtoInfo's ExceptionSpecDecl can point to the // FunctionDecl that we are importing the FunctionProtoType for. // To avoid an infinite recursion when importing, create the FunctionDecl - // with a simplified function type and update it afterwards. + // with a simplified function type. if (FromEPI.ExceptionSpec.SourceDecl || FromEPI.ExceptionSpec.SourceTemplate || FromEPI.ExceptionSpec.NoexceptExpr) { FunctionProtoType::ExtProtoInfo DefaultEPI; - FromTy = Importer.getFromContext().getFunctionType( - FromFPT->getReturnType(), FromFPT->getParamTypes(), DefaultEPI); - usedDifferentExceptionSpec = true; + FromEPI = DefaultEPI; + UsedDifferentProtoType = true; } + FromTy = Importer.getFromContext().getFunctionType( + FromReturnTy, FromFPT->getParamTypes(), FromEPI); } QualType T; TypeSourceInfo *TInfo; SourceLocation ToInnerLocStart, ToEndLoc; NestedNameSpecifierLoc ToQualifierLoc; + Expr *TrailingRequiresClause; if (auto Imp = importSeq( FromTy, D->getTypeSourceInfo(), D->getInnerLocStart(), - D->getQualifierLoc(), D->getEndLoc())) - std::tie(T, TInfo, ToInnerLocStart, ToQualifierLoc, ToEndLoc) = *Imp; + D->getQualifierLoc(), D->getEndLoc(), D->getTrailingRequiresClause())) + std::tie(T, TInfo, ToInnerLocStart, ToQualifierLoc, ToEndLoc, + TrailingRequiresClause) = *Imp; else return Imp.takeError(); @@ -3168,7 +3313,10 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ExplicitSpecifier( ExplicitExpr, FromConstructor->getExplicitSpecifier().getKind()), - D->isInlineSpecified(), D->isImplicit(), D->getConstexprKind())) + D->isInlineSpecified(), D->isImplicit(), D->getConstexprKind(), + InheritedConstructor(), // FIXME: Properly import inherited + // constructor info + TrailingRequiresClause)) return ToFunction; } else if (CXXDestructorDecl *FromDtor = dyn_cast<CXXDestructorDecl>(D)) { @@ -3186,7 +3334,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { if (GetImportedOrCreateDecl<CXXDestructorDecl>( ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), - D->isImplicit(), D->getConstexprKind())) + D->isImplicit(), D->getConstexprKind(), TrailingRequiresClause)) return ToFunction; CXXDestructorDecl *ToDtor = cast<CXXDestructorDecl>(ToFunction); @@ -3206,20 +3354,21 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), ExplicitSpecifier(ExplicitExpr, FromConversion->getExplicitSpecifier().getKind()), - D->getConstexprKind(), SourceLocation())) + D->getConstexprKind(), SourceLocation(), TrailingRequiresClause)) return ToFunction; } else if (auto *Method = dyn_cast<CXXMethodDecl>(D)) { if (GetImportedOrCreateDecl<CXXMethodDecl>( ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), ToInnerLocStart, NameInfo, T, TInfo, Method->getStorageClass(), Method->isInlineSpecified(), D->getConstexprKind(), - SourceLocation())) + SourceLocation(), TrailingRequiresClause)) return ToFunction; } else { if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart, NameInfo, T, TInfo, D->getStorageClass(), D->isInlineSpecified(), - D->hasWrittenPrototype(), D->getConstexprKind())) + D->hasWrittenPrototype(), D->getConstexprKind(), + TrailingRequiresClause)) return ToFunction; } @@ -3263,14 +3412,6 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } } - if (usedDifferentExceptionSpec) { - // Update FunctionProtoType::ExtProtoInfo. - if (ExpectedType TyOrErr = import(D->getType())) - ToFunction->setType(*TyOrErr); - else - return TyOrErr.takeError(); - } - // Import the describing template function, if any. if (FromFT) { auto ToFTOrErr = import(FromFT); @@ -3302,29 +3443,21 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { return std::move(Err); } + // Import and set the original type in case we used another type. + if (UsedDifferentProtoType) { + if (ExpectedType TyOrErr = import(D->getType())) + ToFunction->setType(*TyOrErr); + else + return TyOrErr.takeError(); + } + // FIXME: Other bits to merge? // If it is a template, import all related things. if (Error Err = ImportTemplateInformation(D, ToFunction)) return std::move(Err); - bool IsFriend = D->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend); - - // TODO Can we generalize this approach to other AST nodes as well? - if (D->getDeclContext()->containsDeclAndLoad(D)) - DC->addDeclInternal(ToFunction); - if (DC != LexicalDC && D->getLexicalDeclContext()->containsDeclAndLoad(D)) - LexicalDC->addDeclInternal(ToFunction); - - // Friend declaration's lexical context is the befriending class, but the - // semantic context is the enclosing scope of the befriending class. - // We want the friend functions to be found in the semantic context by lookup. - // FIXME should we handle this generically in VisitFriendDecl? - // In Other cases when LexicalDC != DC we don't want it to be added, - // e.g out-of-class definitions like void B::f() {} . - if (LexicalDC != DC && IsFriend) { - DC->makeDeclVisibleInContext(ToFunction); - } + addDeclToContexts(D, ToFunction); if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D)) if (Error Err = ImportOverriddenMethods(cast<CXXMethodDecl>(ToFunction), @@ -3772,10 +3905,7 @@ ExpectedDecl ASTNodeImporter::VisitVarDecl(VarDecl *D) { if (D->isConstexpr()) ToVar->setConstexpr(true); - if (D->getDeclContext()->containsDeclAndLoad(D)) - DC->addDeclInternal(ToVar); - if (DC != LexicalDC && D->getLexicalDeclContext()->containsDeclAndLoad(D)) - LexicalDC->addDeclInternal(ToVar); + addDeclToContexts(D, ToVar); // Import the rest of the chain. I.e. import all subsequent declarations. for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) { @@ -3961,10 +4091,10 @@ ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { ObjCMethodDecl *ToMethod; if (GetImportedOrCreateDecl( - ToMethod, D, Importer.getToContext(), Loc, - ToEndLoc, Name.getObjCSelector(), ToReturnType, - ToReturnTypeSourceInfo, DC, D->isInstanceMethod(), D->isVariadic(), - D->isPropertyAccessor(), D->isImplicit(), D->isDefined(), + ToMethod, D, Importer.getToContext(), Loc, ToEndLoc, + Name.getObjCSelector(), ToReturnType, ToReturnTypeSourceInfo, DC, + D->isInstanceMethod(), D->isVariadic(), D->isPropertyAccessor(), + D->isSynthesizedAccessorStub(), D->isImplicit(), D->isDefined(), D->getImplementationControl(), D->hasRelatedResultType())) return ToMethod; @@ -3996,6 +4126,14 @@ ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { ToMethod->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToMethod); + + // Implicit params are declared when Sema encounters the definition but this + // never happens when the method is imported. Manually declare the implicit + // params now that the MethodDecl knows its class interface. + if (D->getSelfDecl()) + ToMethod->createImplicitParams(Importer.getToContext(), + ToMethod->getClassInterface()); + return ToMethod; } @@ -4464,6 +4602,20 @@ ExpectedDecl ASTNodeImporter::VisitUnresolvedUsingTypenameDecl( return ToUsing; } +ExpectedDecl ASTNodeImporter::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) { + Decl* ToD = nullptr; + switch (D->getBuiltinTemplateKind()) { + case BuiltinTemplateKind::BTK__make_integer_seq: + ToD = Importer.getToContext().getMakeIntegerSeqDecl(); + break; + case BuiltinTemplateKind::BTK__type_pack_element: + ToD = Importer.getToContext().getTypePackElementDecl(); + break; + } + assert(ToD && "BuiltinTemplateDecl of unsupported kind!"); + Importer.MapImported(D, ToD); + return ToD; +} Error ASTNodeImporter::ImportDefinition( ObjCInterfaceDecl *From, ObjCInterfaceDecl *To, ImportDefinitionKind Kind) { @@ -4945,7 +5097,7 @@ ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { // context. This context will be fixed when the actual template declaration // is created. - // FIXME: Import default argument. + // FIXME: Import default argument and constraint expression. ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc()); if (!BeginLocOrErr) @@ -4956,12 +5108,47 @@ ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { return LocationOrErr.takeError(); TemplateTypeParmDecl *ToD = nullptr; - (void)GetImportedOrCreateDecl( + if (GetImportedOrCreateDecl( ToD, D, Importer.getToContext(), Importer.getToContext().getTranslationUnitDecl(), *BeginLocOrErr, *LocationOrErr, D->getDepth(), D->getIndex(), Importer.Import(D->getIdentifier()), - D->wasDeclaredWithTypename(), D->isParameterPack()); + D->wasDeclaredWithTypename(), D->isParameterPack(), + D->hasTypeConstraint())) + return ToD; + + // Import the type-constraint + if (const TypeConstraint *TC = D->getTypeConstraint()) { + NestedNameSpecifierLoc ToNNS; + DeclarationName ToName; + SourceLocation ToNameLoc; + NamedDecl *ToFoundDecl; + ConceptDecl *ToNamedConcept; + Expr *ToIDC; + if (auto Imp = importSeq(TC->getNestedNameSpecifierLoc(), + TC->getConceptNameInfo().getName(), TC->getConceptNameInfo().getLoc(), + TC->getFoundDecl(), TC->getNamedConcept(), + TC->getImmediatelyDeclaredConstraint())) + std::tie(ToNNS, ToName, ToNameLoc, ToFoundDecl, ToNamedConcept, + ToIDC) = *Imp; + else + return Imp.takeError(); + + TemplateArgumentListInfo ToTAInfo; + const auto *ASTTemplateArgs = TC->getTemplateArgsAsWritten(); + if (ASTTemplateArgs) + if (Error Err = ImportTemplateArgumentListInfo(*ASTTemplateArgs, + ToTAInfo)) + return std::move(Err); + + ToD->setTypeConstraint(ToNNS, DeclarationNameInfo(ToName, ToNameLoc), + ToFoundDecl, ToNamedConcept, + ASTTemplateArgs ? + ASTTemplateArgumentListInfo::Create(Importer.getToContext(), + ToTAInfo) : nullptr, + ToIDC); + } + return ToD; } @@ -5033,7 +5220,6 @@ template <typename T> static auto getTemplateDefinition(T *D) -> T * { } ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { - bool IsFriend = D->getFriendObjectKind() != Decl::FOK_None; // Import the major distinguishing characteristics of this class template. DeclContext *DC, *LexicalDC; @@ -5059,6 +5245,8 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { Decl *Found = FoundDecl; auto *FoundTemplate = dyn_cast<ClassTemplateDecl>(Found); if (FoundTemplate) { + if (!hasSameVisibilityContext(FoundTemplate, D)) + continue; if (IsStructuralMatch(D, FoundTemplate)) { ClassTemplateDecl *TemplateWithDef = @@ -5108,10 +5296,7 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { D2->setAccess(D->getAccess()); D2->setLexicalDeclContext(LexicalDC); - if (D->getDeclContext()->containsDeclAndLoad(D)) - DC->addDeclInternal(D2); - if (DC != LexicalDC && D->getLexicalDeclContext()->containsDeclAndLoad(D)) - LexicalDC->addDeclInternal(D2); + addDeclToContexts(D, D2); if (FoundByLookup) { auto *Recent = @@ -5137,9 +5322,6 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { D2->setPreviousDecl(Recent); } - if (LexicalDC != DC && IsFriend) - DC->makeDeclVisibleInContext(D2); - if (FromTemplated->isCompleteDefinition() && !ToTemplated->isCompleteDefinition()) { // FIXME: Import definition! @@ -5164,16 +5346,25 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( if (Error Err = ImportTemplateArguments( D->getTemplateArgs().data(), D->getTemplateArgs().size(), TemplateArgs)) return std::move(Err); - - // Try to find an existing specialization with these template arguments. + // Try to find an existing specialization with these template arguments and + // template parameter list. void *InsertPos = nullptr; ClassTemplateSpecializationDecl *PrevDecl = nullptr; ClassTemplatePartialSpecializationDecl *PartialSpec = dyn_cast<ClassTemplatePartialSpecializationDecl>(D); - if (PartialSpec) - PrevDecl = - ClassTemplate->findPartialSpecialization(TemplateArgs, InsertPos); - else + + // Import template parameters. + TemplateParameterList *ToTPList = nullptr; + + if (PartialSpec) { + auto ToTPListOrErr = import(PartialSpec->getTemplateParameters()); + if (!ToTPListOrErr) + return ToTPListOrErr.takeError(); + ToTPList = *ToTPListOrErr; + PrevDecl = ClassTemplate->findPartialSpecialization(TemplateArgs, + *ToTPListOrErr, + InsertPos); + } else PrevDecl = ClassTemplate->findSpecialization(TemplateArgs, InsertPos); if (PrevDecl) { @@ -5232,13 +5423,9 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( return std::move(Err); CanonInjType = CanonInjType.getCanonicalType(); - auto ToTPListOrErr = import(PartialSpec->getTemplateParameters()); - if (!ToTPListOrErr) - return ToTPListOrErr.takeError(); - if (GetImportedOrCreateDecl<ClassTemplatePartialSpecializationDecl>( D2, D, Importer.getToContext(), D->getTagKind(), DC, - *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr, ClassTemplate, + *BeginLocOrErr, *IdLocOrErr, ToTPList, ClassTemplate, llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()), ToTAInfo, CanonInjType, cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl))) @@ -5246,10 +5433,11 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( // Update InsertPos, because preceding import calls may have invalidated // it by adding new specializations. - if (!ClassTemplate->findPartialSpecialization(TemplateArgs, InsertPos)) + auto *PartSpec2 = cast<ClassTemplatePartialSpecializationDecl>(D2); + if (!ClassTemplate->findPartialSpecialization(TemplateArgs, ToTPList, + InsertPos)) // Add this partial specialization to the class template. - ClassTemplate->AddPartialSpecialization( - cast<ClassTemplatePartialSpecializationDecl>(D2), InsertPos); + ClassTemplate->AddPartialSpecialization(PartSpec2, InsertPos); } else { // Not a partial specialization. if (GetImportedOrCreateDecl( @@ -5275,6 +5463,11 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( LexicalDC->addDeclInternal(D2); } + if (auto BraceRangeOrErr = import(D->getBraceRange())) + D2->setBraceRange(*BraceRangeOrErr); + else + return BraceRangeOrErr.takeError(); + // Import the qualifier, if any. if (auto LocOrErr = import(D->getQualifierLoc())) D2->setQualifierInfo(*LocOrErr); @@ -6273,7 +6466,8 @@ ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { TemplateArgumentListInfo *ToResInfo = nullptr; if (E->hasExplicitTemplateArgs()) { if (Error Err = - ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo)) + ImportTemplateArgumentListInfo(E->getLAngleLoc(), E->getRAngleLoc(), + E->template_arguments(), ToTAInfo)) return std::move(Err); ToResInfo = &ToTAInfo; } @@ -6989,23 +7183,52 @@ ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) { E->requiresZeroInitialization()); } +ExpectedDecl ASTNodeImporter::VisitLifetimeExtendedTemporaryDecl( + LifetimeExtendedTemporaryDecl *D) { + DeclContext *DC, *LexicalDC; + if (Error Err = ImportDeclContext(D, DC, LexicalDC)) + return std::move(Err); + + auto Imp = importSeq(D->getTemporaryExpr(), D->getExtendingDecl()); + // FIXME: the APValue should be imported as well if present. + if (!Imp) + return Imp.takeError(); + + Expr *Temporary; + ValueDecl *ExtendingDecl; + std::tie(Temporary, ExtendingDecl) = *Imp; + // FIXME: Should ManglingNumber get numbers associated with 'to' context? + + LifetimeExtendedTemporaryDecl *To; + if (GetImportedOrCreateDecl(To, D, Temporary, ExtendingDecl, + D->getManglingNumber())) + return To; + + To->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(To); + return To; +} + ExpectedStmt ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { - auto Imp = importSeq( - E->getType(), E->GetTemporaryExpr(), E->getExtendingDecl()); + auto Imp = importSeq(E->getType(), + E->getLifetimeExtendedTemporaryDecl() ? nullptr + : E->getSubExpr(), + E->getLifetimeExtendedTemporaryDecl()); if (!Imp) return Imp.takeError(); QualType ToType; Expr *ToTemporaryExpr; - const ValueDecl *ToExtendingDecl; - std::tie(ToType, ToTemporaryExpr, ToExtendingDecl) = *Imp; + LifetimeExtendedTemporaryDecl *ToMaterializedDecl; + std::tie(ToType, ToTemporaryExpr, ToMaterializedDecl) = *Imp; + if (!ToTemporaryExpr) + ToTemporaryExpr = cast<Expr>(ToMaterializedDecl->getTemporaryExpr()); - auto *ToMTE = new (Importer.getToContext()) MaterializeTemporaryExpr( - ToType, ToTemporaryExpr, E->isBoundToLvalueReference()); + auto *ToMTE = new (Importer.getToContext()) MaterializeTemporaryExpr( + ToType, ToTemporaryExpr, E->isBoundToLvalueReference(), + ToMaterializedDecl); - // FIXME: Should ManglingNumber get numbers associated with 'to' context? - ToMTE->setExtendingDecl(ToExtendingDecl, E->getManglingNumber()); return ToMTE; } @@ -7320,20 +7543,19 @@ ExpectedStmt ASTNodeImporter::VisitCXXDependentScopeMemberExpr( ExpectedStmt ASTNodeImporter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { - auto Imp = importSeq( - E->getQualifierLoc(), E->getTemplateKeywordLoc(), E->getDeclName(), - E->getExprLoc(), E->getLAngleLoc(), E->getRAngleLoc()); + auto Imp = importSeq(E->getQualifierLoc(), E->getTemplateKeywordLoc(), + E->getDeclName(), E->getNameInfo().getLoc(), + E->getLAngleLoc(), E->getRAngleLoc()); if (!Imp) return Imp.takeError(); NestedNameSpecifierLoc ToQualifierLoc; - SourceLocation ToTemplateKeywordLoc, ToExprLoc, ToLAngleLoc, ToRAngleLoc; + SourceLocation ToTemplateKeywordLoc, ToNameLoc, ToLAngleLoc, ToRAngleLoc; DeclarationName ToDeclName; - std::tie( - ToQualifierLoc, ToTemplateKeywordLoc, ToDeclName, ToExprLoc, - ToLAngleLoc, ToRAngleLoc) = *Imp; + std::tie(ToQualifierLoc, ToTemplateKeywordLoc, ToDeclName, ToNameLoc, + ToLAngleLoc, ToRAngleLoc) = *Imp; - DeclarationNameInfo ToNameInfo(ToDeclName, ToExprLoc); + DeclarationNameInfo ToNameInfo(ToDeclName, ToNameLoc); if (Error Err = ImportDeclarationNameLoc(E->getNameInfo(), ToNameInfo)) return std::move(Err); @@ -7398,7 +7620,7 @@ ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { else return ToDOrErr.takeError(); - if (E->hasExplicitTemplateArgs() && E->getTemplateKeywordLoc().isValid()) { + if (E->hasExplicitTemplateArgs()) { TemplateArgumentListInfo ToTAInfo; if (Error Err = ImportTemplateArgumentListInfo( E->getLAngleLoc(), E->getRAngleLoc(), E->template_arguments(), @@ -7452,8 +7674,9 @@ ASTNodeImporter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { TemplateArgumentListInfo ToTAInfo; TemplateArgumentListInfo *ResInfo = nullptr; if (E->hasExplicitTemplateArgs()) { - if (Error Err = - ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo)) + TemplateArgumentListInfo FromTAInfo; + E->copyTemplateArgumentsInto(FromTAInfo); + if (Error Err = ImportTemplateArgumentListInfo(FromTAInfo, ToTAInfo)) return std::move(Err); ResInfo = &ToTAInfo; } @@ -8266,8 +8489,14 @@ ASTImporter::Import(NestedNameSpecifierLoc FromNNS) { return std::move(Err); TypeSourceInfo *TSI = getToContext().getTrivialTypeSourceInfo( QualType(Spec->getAsType(), 0), ToTLoc); - Builder.Extend(getToContext(), ToLocalBeginLoc, TSI->getTypeLoc(), - ToLocalEndLoc); + if (Kind == NestedNameSpecifier::TypeSpecWithTemplate) + // ToLocalBeginLoc is here the location of the 'template' keyword. + Builder.Extend(getToContext(), ToLocalBeginLoc, TSI->getTypeLoc(), + ToLocalEndLoc); + else + // No location for 'template' keyword here. + Builder.Extend(getToContext(), SourceLocation{}, TSI->getTypeLoc(), + ToLocalEndLoc); break; } diff --git a/clang/lib/AST/ASTTypeTraits.cpp b/clang/lib/AST/ASTTypeTraits.cpp index 6b7f6ec51086..a5570c329ae8 100644 --- a/clang/lib/AST/ASTTypeTraits.cpp +++ b/clang/lib/AST/ASTTypeTraits.cpp @@ -16,6 +16,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/OpenMPClause.h" namespace clang { namespace ast_type_traits { diff --git a/clang/lib/AST/Comment.cpp b/clang/lib/AST/Comment.cpp index 23dc7ba93591..a02cc9d119fe 100644 --- a/clang/lib/AST/Comment.cpp +++ b/clang/lib/AST/Comment.cpp @@ -379,11 +379,11 @@ StringRef TParamCommandComment::getParamName(const FullComment *FC) const { assert(isPositionValid()); const TemplateParameterList *TPL = FC->getDeclInfo()->TemplateParameters; for (unsigned i = 0, e = getDepth(); i != e; ++i) { - if (i == e-1) + assert(TPL && "Unknown TemplateParameterList"); + if (i == e - 1) return TPL->getParam(getIndex(i))->getName(); const NamedDecl *Param = TPL->getParam(getIndex(i)); - if (const TemplateTemplateParmDecl *TTP = - dyn_cast<TemplateTemplateParmDecl>(Param)) + if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Param)) TPL = TTP->getTemplateParameters(); } return ""; diff --git a/clang/lib/AST/CommentSema.cpp b/clang/lib/AST/CommentSema.cpp index 69d61dc55162..53c1832d1dd2 100644 --- a/clang/lib/AST/CommentSema.cpp +++ b/clang/lib/AST/CommentSema.cpp @@ -676,9 +676,8 @@ void Sema::checkDeprecatedCommand(const BlockCommandComment *Command) { D->hasAttr<UnavailableAttr>()) return; - Diag(Command->getLocation(), - diag::warn_doc_deprecated_not_sync) - << Command->getSourceRange(); + Diag(Command->getLocation(), diag::warn_doc_deprecated_not_sync) + << Command->getSourceRange() << Command->getCommandMarker(); // Try to emit a fixit with a deprecation attribute. if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { @@ -689,24 +688,41 @@ void Sema::checkDeprecatedCommand(const BlockCommandComment *Command) { FD->doesThisDeclarationHaveABody()) return; - StringRef AttributeSpelling = "__attribute__((deprecated))"; + const LangOptions &LO = FD->getASTContext().getLangOpts(); + const bool DoubleSquareBracket = LO.CPlusPlus14 || LO.C2x; + StringRef AttributeSpelling = + DoubleSquareBracket ? "[[deprecated]]" : "__attribute__((deprecated))"; if (PP) { - TokenValue Tokens[] = { - tok::kw___attribute, tok::l_paren, tok::l_paren, - PP->getIdentifierInfo("deprecated"), - tok::r_paren, tok::r_paren - }; - StringRef MacroName = PP->getLastMacroWithSpelling(FD->getLocation(), - Tokens); - if (!MacroName.empty()) - AttributeSpelling = MacroName; + // Try to find a replacement macro: + // - In C2x/C++14 we prefer [[deprecated]]. + // - If not found or an older C/C++ look for __attribute__((deprecated)). + StringRef MacroName; + if (DoubleSquareBracket) { + TokenValue Tokens[] = {tok::l_square, tok::l_square, + PP->getIdentifierInfo("deprecated"), + tok::r_square, tok::r_square}; + MacroName = PP->getLastMacroWithSpelling(FD->getLocation(), Tokens); + if (!MacroName.empty()) + AttributeSpelling = MacroName; + } + + if (MacroName.empty()) { + TokenValue Tokens[] = { + tok::kw___attribute, tok::l_paren, + tok::l_paren, PP->getIdentifierInfo("deprecated"), + tok::r_paren, tok::r_paren}; + StringRef MacroName = + PP->getLastMacroWithSpelling(FD->getLocation(), Tokens); + if (!MacroName.empty()) + AttributeSpelling = MacroName; + } } - SmallString<64> TextToInsert(" "); - TextToInsert += AttributeSpelling; - Diag(FD->getEndLoc(), diag::note_add_deprecation_attr) - << FixItHint::CreateInsertion(FD->getEndLoc().getLocWithOffset(1), - TextToInsert); + SmallString<64> TextToInsert = AttributeSpelling; + TextToInsert += " "; + SourceLocation Loc = FD->getSourceRange().getBegin(); + Diag(Loc, diag::note_add_deprecation_attr) + << FixItHint::CreateInsertion(Loc, TextToInsert); } } @@ -1127,6 +1143,7 @@ Sema::getInlineCommandRenderKind(StringRef Name) const { .Case("b", InlineCommandComment::RenderBold) .Cases("c", "p", InlineCommandComment::RenderMonospaced) .Cases("a", "e", "em", InlineCommandComment::RenderEmphasized) + .Case("anchor", InlineCommandComment::RenderAnchor) .Default(InlineCommandComment::RenderNormal); } diff --git a/clang/lib/AST/ComparisonCategories.cpp b/clang/lib/AST/ComparisonCategories.cpp index ee4c1b0443a3..07673230357f 100644 --- a/clang/lib/AST/ComparisonCategories.cpp +++ b/clang/lib/AST/ComparisonCategories.cpp @@ -19,6 +19,26 @@ using namespace clang; +Optional<ComparisonCategoryType> +clang::getComparisonCategoryForBuiltinCmp(QualType T) { + using CCT = ComparisonCategoryType; + + if (T->isIntegralOrEnumerationType()) + return CCT::StrongOrdering; + + if (T->isRealFloatingType()) + return CCT::PartialOrdering; + + // C++2a [expr.spaceship]p8: If the composite pointer type is an object + // pointer type, p <=> q is of type std::strong_ordering. + // Note: this assumes neither operand is a null pointer constant. + if (T->isObjectPointerType()) + return CCT::StrongOrdering; + + // TODO: Extend support for operator<=> to ObjC types. + return llvm::None; +} + bool ComparisonCategoryInfo::ValueInfo::hasValidIntValue() const { assert(VD && "must have var decl"); if (!VD->checkInitIsICE()) @@ -59,7 +79,7 @@ ComparisonCategoryInfo::ValueInfo *ComparisonCategoryInfo::lookupValueInfo( // a new entry representing it. DeclContextLookupResult Lookup = Record->getCanonicalDecl()->lookup( &Ctx.Idents.get(ComparisonCategories::getResultString(ValueKind))); - if (Lookup.size() != 1 || !isa<VarDecl>(Lookup.front())) + if (Lookup.empty() || !isa<VarDecl>(Lookup.front())) return nullptr; Objects.emplace_back(ValueKind, cast<VarDecl>(Lookup.front())); return &Objects.back(); @@ -70,7 +90,7 @@ static const NamespaceDecl *lookupStdNamespace(const ASTContext &Ctx, if (!StdNS) { DeclContextLookupResult Lookup = Ctx.getTranslationUnitDecl()->lookup(&Ctx.Idents.get("std")); - if (Lookup.size() == 1) + if (!Lookup.empty()) StdNS = dyn_cast<NamespaceDecl>(Lookup.front()); } return StdNS; @@ -81,7 +101,7 @@ static CXXRecordDecl *lookupCXXRecordDecl(const ASTContext &Ctx, ComparisonCategoryType Kind) { StringRef Name = ComparisonCategories::getCategoryString(Kind); DeclContextLookupResult Lookup = StdNS->lookup(&Ctx.Idents.get(Name)); - if (Lookup.size() == 1) + if (!Lookup.empty()) if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Lookup.front())) return RD; return nullptr; @@ -150,10 +170,6 @@ QualType ComparisonCategoryInfo::getType() const { StringRef ComparisonCategories::getCategoryString(ComparisonCategoryType Kind) { using CCKT = ComparisonCategoryType; switch (Kind) { - case CCKT::WeakEquality: - return "weak_equality"; - case CCKT::StrongEquality: - return "strong_equality"; case CCKT::PartialOrdering: return "partial_ordering"; case CCKT::WeakOrdering: @@ -169,12 +185,8 @@ StringRef ComparisonCategories::getResultString(ComparisonCategoryResult Kind) { switch (Kind) { case CCVT::Equal: return "equal"; - case CCVT::Nonequal: - return "nonequal"; case CCVT::Equivalent: return "equivalent"; - case CCVT::Nonequivalent: - return "nonequivalent"; case CCVT::Less: return "less"; case CCVT::Greater: @@ -190,20 +202,11 @@ ComparisonCategories::getPossibleResultsForType(ComparisonCategoryType Type) { using CCT = ComparisonCategoryType; using CCR = ComparisonCategoryResult; std::vector<CCR> Values; - Values.reserve(6); - Values.push_back(CCR::Equivalent); - bool IsStrong = (Type == CCT::StrongEquality || Type == CCT::StrongOrdering); - if (IsStrong) - Values.push_back(CCR::Equal); - if (Type == CCT::StrongOrdering || Type == CCT::WeakOrdering || - Type == CCT::PartialOrdering) { - Values.push_back(CCR::Less); - Values.push_back(CCR::Greater); - } else { - Values.push_back(CCR::Nonequivalent); - if (IsStrong) - Values.push_back(CCR::Nonequal); - } + Values.reserve(4); + bool IsStrong = Type == CCT::StrongOrdering; + Values.push_back(IsStrong ? CCR::Equal : CCR::Equivalent); + Values.push_back(CCR::Less); + Values.push_back(CCR::Greater); if (Type == CCT::PartialOrdering) Values.push_back(CCR::Unordered); return Values; diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 80235d8496d2..0d30f64b992e 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -16,6 +16,7 @@ #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ASTLambda.h" #include "clang/AST/ASTMutationListener.h" +#include "clang/AST/Attr.h" #include "clang/AST/CanonicalType.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" @@ -55,8 +56,8 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" @@ -901,6 +902,10 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, if (!isExternallyVisible(LV.getLinkage())) return LinkageInfo(LV.getLinkage(), DefaultVisibility, false); + // Mark the symbols as hidden when compiling for the device. + if (Context.getLangOpts().OpenMP && Context.getLangOpts().OpenMPIsDevice) + LV.mergeVisibility(HiddenVisibility, /*newExplicit=*/false); + return LV; } @@ -1815,6 +1820,12 @@ SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const { return SourceLocation(); } +SourceLocation DeclaratorDecl::getTypeSpecEndLoc() const { + TypeSourceInfo *TSI = getTypeSourceInfo(); + if (TSI) return TSI->getTypeLoc().getEndLoc(); + return SourceLocation(); +} + void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { if (QualifierLoc) { // Make sure the extended decl info is allocated. @@ -1828,23 +1839,27 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { } // Set qualifier info. getExtInfo()->QualifierLoc = QualifierLoc; - } else { + } else if (hasExtInfo()) { // Here Qualifier == 0, i.e., we are removing the qualifier (if any). - if (hasExtInfo()) { - if (getExtInfo()->NumTemplParamLists == 0) { - // Save type source info pointer. - TypeSourceInfo *savedTInfo = getExtInfo()->TInfo; - // Deallocate the extended decl info. - getASTContext().Deallocate(getExtInfo()); - // Restore savedTInfo into (non-extended) decl info. - DeclInfo = savedTInfo; - } - else - getExtInfo()->QualifierLoc = QualifierLoc; - } + getExtInfo()->QualifierLoc = QualifierLoc; } } +void DeclaratorDecl::setTrailingRequiresClause(Expr *TrailingRequiresClause) { + assert(TrailingRequiresClause); + // Make sure the extended decl info is allocated. + if (!hasExtInfo()) { + // Save (non-extended) type source info pointer. + auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>(); + // Allocate external info struct. + DeclInfo = new (getASTContext()) ExtInfo; + // Restore savedTInfo into (extended) decl info. + getExtInfo()->TInfo = savedTInfo; + } + // Set requires clause info. + getExtInfo()->TrailingRequiresClause = TrailingRequiresClause; +} + void DeclaratorDecl::setTemplateParameterListsInfo( ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) { assert(!TPLists.empty()); @@ -2766,10 +2781,11 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass S, bool isInlineSpecified, - ConstexprSpecKind ConstexprKind) + ConstexprSpecKind ConstexprKind, + Expr *TrailingRequiresClause) : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo, StartLoc), - DeclContext(DK), redeclarable_base(C), ODRHash(0), + DeclContext(DK), redeclarable_base(C), Body(), ODRHash(0), EndRangeLoc(NameInfo.getEndLoc()), DNLoc(NameInfo.getInfo()) { assert(T.isNull() || T->isFunctionType()); FunctionDeclBits.SClass = S; @@ -2784,16 +2800,20 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, FunctionDeclBits.IsTrivialForCall = false; FunctionDeclBits.IsDefaulted = false; FunctionDeclBits.IsExplicitlyDefaulted = false; + FunctionDeclBits.HasDefaultedFunctionInfo = false; FunctionDeclBits.HasImplicitReturnZero = false; FunctionDeclBits.IsLateTemplateParsed = false; FunctionDeclBits.ConstexprKind = ConstexprKind; FunctionDeclBits.InstantiationIsPending = false; FunctionDeclBits.UsesSEHTry = false; + FunctionDeclBits.UsesFPIntrin = false; FunctionDeclBits.HasSkippedBody = false; FunctionDeclBits.WillHaveBody = false; FunctionDeclBits.IsMultiVersion = false; FunctionDeclBits.IsCopyDeductionCandidate = false; FunctionDeclBits.HasODRHash = false; + if (TrailingRequiresClause) + setTrailingRequiresClause(TrailingRequiresClause); } void FunctionDecl::getNameForDiagnostic( @@ -2810,6 +2830,32 @@ bool FunctionDecl::isVariadic() const { return false; } +FunctionDecl::DefaultedFunctionInfo * +FunctionDecl::DefaultedFunctionInfo::Create(ASTContext &Context, + ArrayRef<DeclAccessPair> Lookups) { + DefaultedFunctionInfo *Info = new (Context.Allocate( + totalSizeToAlloc<DeclAccessPair>(Lookups.size()), + std::max(alignof(DefaultedFunctionInfo), alignof(DeclAccessPair)))) + DefaultedFunctionInfo; + Info->NumLookups = Lookups.size(); + std::uninitialized_copy(Lookups.begin(), Lookups.end(), + Info->getTrailingObjects<DeclAccessPair>()); + return Info; +} + +void FunctionDecl::setDefaultedFunctionInfo(DefaultedFunctionInfo *Info) { + assert(!FunctionDeclBits.HasDefaultedFunctionInfo && "already have this"); + assert(!Body && "can't replace function body with defaulted function info"); + + FunctionDeclBits.HasDefaultedFunctionInfo = true; + DefaultedInfo = Info; +} + +FunctionDecl::DefaultedFunctionInfo * +FunctionDecl::getDefaultedFunctionInfo() const { + return FunctionDeclBits.HasDefaultedFunctionInfo ? DefaultedInfo : nullptr; +} + bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const { for (auto I : redecls()) { if (I->doesThisDeclarationHaveABody()) { @@ -2821,8 +2867,7 @@ bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const { return false; } -bool FunctionDecl::hasTrivialBody() const -{ +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 @@ -2850,6 +2895,8 @@ Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { if (!hasBody(Definition)) return nullptr; + assert(!Definition->FunctionDeclBits.HasDefaultedFunctionInfo && + "definition should not have a body"); if (Definition->Body) return Definition->Body.get(getASTContext().getExternalSource()); @@ -2857,7 +2904,8 @@ Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { } void FunctionDecl::setBody(Stmt *B) { - Body = B; + FunctionDeclBits.HasDefaultedFunctionInfo = false; + Body = LazyDeclStmtPtr(B); if (B) EndRangeLoc = B->getEndLoc(); } @@ -2998,6 +3046,14 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction(bool *IsAligned) const return Params == FPT->getNumParams(); } +bool FunctionDecl::isInlineBuiltinDeclaration() const { + if (!getBuiltinID()) + return false; + + const FunctionDecl *Definition; + return hasBody(Definition) && Definition->isInlineSpecified(); +} + bool FunctionDecl::isDestroyingOperatorDelete() const { // C++ P0722: // Within a class C, a single object deallocation function with signature @@ -3115,10 +3171,17 @@ FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); } /// functions as their wrapped builtins. This shouldn't be done in general, but /// it's useful in Sema to diagnose calls to wrappers based on their semantics. unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const { - if (!getIdentifier()) - return 0; + unsigned BuiltinID; + + if (const auto *AMAA = getAttr<ArmMveAliasAttr>()) { + BuiltinID = AMAA->getBuiltinName()->getBuiltinID(); + } else { + if (!getIdentifier()) + return 0; + + BuiltinID = getIdentifier()->getBuiltinID(); + } - unsigned BuiltinID = getIdentifier()->getBuiltinID(); if (!BuiltinID) return 0; @@ -3142,7 +3205,8 @@ unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const { // If the function is marked "overloadable", it has a different mangled name // and is not the C library function. - if (!ConsiderWrapperFunctions && hasAttr<OverloadableAttr>()) + if (!ConsiderWrapperFunctions && hasAttr<OverloadableAttr>() && + !hasAttr<ArmMveAliasAttr>()) return 0; if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) @@ -3290,9 +3354,9 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { const FunctionDecl *Prev = this; bool FoundBody = false; while ((Prev = Prev->getPreviousDecl())) { - FoundBody |= Prev->Body.isValid(); + FoundBody |= Prev->doesThisDeclarationHaveABody(); - if (Prev->Body) { + if (Prev->doesThisDeclarationHaveABody()) { // If it's not the case that both 'inline' and 'extern' are // specified on the definition, then it is always externally visible. if (!Prev->isInlineSpecified() || @@ -3315,19 +3379,21 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { const FunctionDecl *Prev = this; bool FoundBody = false; while ((Prev = Prev->getPreviousDecl())) { - FoundBody |= Prev->Body.isValid(); + FoundBody |= Prev->doesThisDeclarationHaveABody(); if (RedeclForcesDefC99(Prev)) return false; } return FoundBody; } -SourceRange FunctionDecl::getReturnTypeSourceRange() const { +FunctionTypeLoc FunctionDecl::getFunctionTypeLoc() const { const TypeSourceInfo *TSI = getTypeSourceInfo(); - if (!TSI) - return SourceRange(); - FunctionTypeLoc FTL = - TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>(); + return TSI ? TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>() + : FunctionTypeLoc(); +} + +SourceRange FunctionDecl::getReturnTypeSourceRange() const { + FunctionTypeLoc FTL = getFunctionTypeLoc(); if (!FTL) return SourceRange(); @@ -3342,16 +3408,25 @@ SourceRange FunctionDecl::getReturnTypeSourceRange() const { return RTRange; } -SourceRange FunctionDecl::getExceptionSpecSourceRange() const { - const TypeSourceInfo *TSI = getTypeSourceInfo(); - if (!TSI) - return SourceRange(); - FunctionTypeLoc FTL = - TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>(); - if (!FTL) +SourceRange FunctionDecl::getParametersSourceRange() const { + unsigned NP = getNumParams(); + SourceLocation EllipsisLoc = getEllipsisLoc(); + + if (NP == 0 && EllipsisLoc.isInvalid()) return SourceRange(); - return FTL.getExceptionSpecRange(); + SourceLocation Begin = + NP > 0 ? ParamInfo[0]->getSourceRange().getBegin() : EllipsisLoc; + SourceLocation End = EllipsisLoc.isValid() + ? EllipsisLoc + : ParamInfo[NP - 1]->getSourceRange().getEnd(); + + return SourceRange(Begin, End); +} + +SourceRange FunctionDecl::getExceptionSpecSourceRange() const { + FunctionTypeLoc FTL = getFunctionTypeLoc(); + return FTL ? FTL.getExceptionSpecRange() : SourceRange(); } /// For an inline function definition in C, or for a gnu_inline function @@ -3812,6 +3887,11 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { case Builtin::BImemcpy: return Builtin::BImemcpy; + case Builtin::BI__builtin_mempcpy: + case Builtin::BI__builtin___mempcpy_chk: + case Builtin::BImempcpy: + return Builtin::BImempcpy; + case Builtin::BI__builtin_memmove: case Builtin::BI__builtin___memmove_chk: case Builtin::BImemmove: @@ -3869,6 +3949,8 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { return Builtin::BImemset; else if (FnInfo->isStr("memcpy")) return Builtin::BImemcpy; + else if (FnInfo->isStr("mempcpy")) + return Builtin::BImempcpy; else if (FnInfo->isStr("memmove")) return Builtin::BImemmove; else if (FnInfo->isStr("memcmp")) @@ -4582,7 +4664,7 @@ LabelDecl *LabelDecl::CreateDeserialized(ASTContext &C, unsigned ID) { } void LabelDecl::setMSAsmLabel(StringRef Name) { - char *Buffer = new (getASTContext(), 1) char[Name.size() + 1]; +char *Buffer = new (getASTContext(), 1) char[Name.size() + 1]; memcpy(Buffer, Name.data(), Name.size()); Buffer[Name.size()] = '\0'; MSAsmName = Buffer; @@ -4623,10 +4705,12 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool isInlineSpecified, bool hasWrittenPrototype, - ConstexprSpecKind ConstexprKind) { + ConstexprSpecKind ConstexprKind, + Expr *TrailingRequiresClause) { FunctionDecl *New = new (C, DC) FunctionDecl(Function, C, DC, StartLoc, NameInfo, T, TInfo, - SC, isInlineSpecified, ConstexprKind); + SC, isInlineSpecified, ConstexprKind, + TrailingRequiresClause); New->setHasWrittenPrototype(hasWrittenPrototype); return New; } @@ -4634,7 +4718,7 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) FunctionDecl(Function, C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, - SC_None, false, CSK_unspecified); + SC_None, false, CSK_unspecified, nullptr); } BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 77a3a4c679a1..6ee767ccecf7 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -803,6 +803,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case OMPRequires: case OMPCapturedExpr: case Empty: + case LifetimeExtendedTemporary: // Never looked up by name. return 0; } diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 12ec44fa0279..2ead1e70ea0d 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -15,6 +15,7 @@ #include "clang/AST/ASTLambda.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/ASTUnresolvedSet.h" +#include "clang/AST/Attr.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclTemplate.h" @@ -413,7 +414,7 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, data().HasIrrelevantDestructor = false; // C++11 [class.copy]p18: - // The implicitly-declared copy assignment oeprator for a class X will + // The implicitly-declared copy assignment operator for a class X will // have the form 'X& X::operator=(const X&)' if each direct base class B // of X has a copy assignment operator whose parameter is of type 'const // B&', 'const volatile B&', or 'B' [...] @@ -737,49 +738,55 @@ void CXXRecordDecl::addedMember(Decl *D) { // Handle constructors. if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(D)) { - if (!Constructor->isImplicit()) { - // Note that we have a user-declared constructor. - data().UserDeclaredConstructor = true; + if (Constructor->isInheritingConstructor()) { + // Ignore constructor shadow declarations. They are lazily created and + // so shouldn't affect any properties of the class. + } else { + if (!Constructor->isImplicit()) { + // Note that we have a user-declared constructor. + data().UserDeclaredConstructor = true; + + // 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; + } - // 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; - } + if (Constructor->isDefaultConstructor()) { + SMKind |= SMF_DefaultConstructor; - if (Constructor->isDefaultConstructor()) { - SMKind |= SMF_DefaultConstructor; + if (Constructor->isUserProvided()) + data().UserProvidedDefaultConstructor = true; + if (Constructor->isConstexpr()) + data().HasConstexprDefaultConstructor = true; + if (Constructor->isDefaulted()) + data().HasDefaultedDefaultConstructor = true; + } - if (Constructor->isUserProvided()) - data().UserProvidedDefaultConstructor = true; - if (Constructor->isConstexpr()) - data().HasConstexprDefaultConstructor = true; - if (Constructor->isDefaulted()) - data().HasDefaultedDefaultConstructor = true; - } + if (!FunTmpl) { + unsigned Quals; + if (Constructor->isCopyConstructor(Quals)) { + SMKind |= SMF_CopyConstructor; - if (!FunTmpl) { - unsigned Quals; - if (Constructor->isCopyConstructor(Quals)) { - SMKind |= SMF_CopyConstructor; + if (Quals & Qualifiers::Const) + data().HasDeclaredCopyConstructorWithConstParam = true; + } else if (Constructor->isMoveConstructor()) + SMKind |= SMF_MoveConstructor; + } - if (Quals & Qualifiers::Const) - data().HasDeclaredCopyConstructorWithConstParam = true; - } else if (Constructor->isMoveConstructor()) - SMKind |= SMF_MoveConstructor; + // C++11 [dcl.init.aggr]p1: DR1518 + // An aggregate is an array or a class with no user-provided [or] + // explicit [...] constructors + // C++20 [dcl.init.aggr]p1: + // An aggregate is an array or a class with no user-declared [...] + // constructors + if (getASTContext().getLangOpts().CPlusPlus2a + ? !Constructor->isImplicit() + : (Constructor->isUserProvided() || Constructor->isExplicit())) + data().Aggregate = false; } - - // C++11 [dcl.init.aggr]p1: DR1518 - // An aggregate is an array or a class with no user-provided [or] - // explicit [...] constructors - // C++20 [dcl.init.aggr]p1: - // An aggregate is an array or a class with no user-declared [...] - // constructors - if (getASTContext().getLangOpts().CPlusPlus2a - ? !Constructor->isImplicit() - : (Constructor->isUserProvided() || Constructor->isExplicit())) - data().Aggregate = false; } // Handle constructors, including those inherited from base classes. @@ -1511,14 +1518,12 @@ static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) { /// \param VOutput the set to which to add conversions from virtual bases /// \param HiddenVBaseCs the set of conversions which were hidden in a /// virtual base along some inheritance path -static void CollectVisibleConversions(ASTContext &Context, - CXXRecordDecl *Record, - bool InVirtual, - AccessSpecifier Access, - const llvm::SmallPtrSet<CanQualType, 8> &ParentHiddenTypes, - ASTUnresolvedSet &Output, - UnresolvedSetImpl &VOutput, - llvm::SmallPtrSet<NamedDecl*, 8> &HiddenVBaseCs) { +static void CollectVisibleConversions( + ASTContext &Context, const CXXRecordDecl *Record, bool InVirtual, + AccessSpecifier Access, + const llvm::SmallPtrSet<CanQualType, 8> &ParentHiddenTypes, + ASTUnresolvedSet &Output, UnresolvedSetImpl &VOutput, + llvm::SmallPtrSet<NamedDecl *, 8> &HiddenVBaseCs) { // The set of types which have conversions in this class or its // subclasses. As an optimization, we don't copy the derived set // unless it might change. @@ -1559,7 +1564,7 @@ static void CollectVisibleConversions(ASTContext &Context, // Collect information recursively from any base classes. for (const auto &I : Record->bases()) { - const RecordType *RT = I.getType()->getAs<RecordType>(); + const auto *RT = I.getType()->getAs<RecordType>(); if (!RT) continue; AccessSpecifier BaseAccess @@ -1577,7 +1582,7 @@ static void CollectVisibleConversions(ASTContext &Context, /// This would be extremely straightforward if it weren't for virtual /// bases. It might be worth special-casing that, really. static void CollectVisibleConversions(ASTContext &Context, - CXXRecordDecl *Record, + const CXXRecordDecl *Record, ASTUnresolvedSet &Output) { // The collection of all conversions in virtual bases that we've // found. These will be added to the output as long as they don't @@ -1601,7 +1606,7 @@ static void CollectVisibleConversions(ASTContext &Context, // Recursively collect conversions from base classes. for (const auto &I : Record->bases()) { - const RecordType *RT = I.getType()->getAs<RecordType>(); + const auto *RT = I.getType()->getAs<RecordType>(); if (!RT) continue; CollectVisibleConversions(Context, cast<CXXRecordDecl>(RT->getDecl()), @@ -1620,7 +1625,7 @@ static void CollectVisibleConversions(ASTContext &Context, /// getVisibleConversionFunctions - get all conversion functions visible /// in current class; including conversion function templates. llvm::iterator_range<CXXRecordDecl::conversion_iterator> -CXXRecordDecl::getVisibleConversionFunctions() { +CXXRecordDecl::getVisibleConversionFunctions() const { ASTContext &Ctx = getASTContext(); ASTUnresolvedSet *Set; @@ -2042,16 +2047,19 @@ CXXMethodDecl *CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool isInline, ConstexprSpecKind ConstexprKind, - SourceLocation EndLocation) { + SourceLocation EndLocation, + Expr *TrailingRequiresClause) { return new (C, RD) CXXMethodDecl(CXXMethod, C, RD, StartLoc, NameInfo, T, TInfo, SC, - isInline, ConstexprKind, EndLocation); + isInline, ConstexprKind, EndLocation, + TrailingRequiresClause); } CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) CXXMethodDecl( CXXMethod, C, nullptr, SourceLocation(), DeclarationNameInfo(), - QualType(), nullptr, SC_None, false, CSK_unspecified, SourceLocation()); + QualType(), nullptr, SC_None, false, CSK_unspecified, SourceLocation(), + nullptr); } CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base, @@ -2432,9 +2440,11 @@ CXXConstructorDecl::CXXConstructorDecl( ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, ExplicitSpecifier ES, bool isInline, bool isImplicitlyDeclared, - ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited) + ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited, + Expr *TrailingRequiresClause) : CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo, - SC_None, isInline, ConstexprKind, SourceLocation()) { + SC_None, isInline, ConstexprKind, SourceLocation(), + TrailingRequiresClause) { setNumCtorInitializers(0); setInheritingConstructor(static_cast<bool>(Inherited)); setImplicit(isImplicitlyDeclared); @@ -2458,7 +2468,7 @@ CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C, auto *Result = new (C, ID, Extra) CXXConstructorDecl(C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, ExplicitSpecifier(), false, false, - CSK_unspecified, InheritedConstructor()); + CSK_unspecified, InheritedConstructor(), nullptr); Result->setInheritingConstructor(isInheritingConstructor); Result->CXXConstructorDeclBits.HasTrailingExplicitSpecifier = hasTraillingExplicit; @@ -2470,7 +2480,8 @@ CXXConstructorDecl *CXXConstructorDecl::Create( ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, ExplicitSpecifier ES, bool isInline, bool isImplicitlyDeclared, - ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited) { + ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited, + Expr *TrailingRequiresClause) { assert(NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName && "Name must refer to a constructor"); @@ -2479,7 +2490,8 @@ CXXConstructorDecl *CXXConstructorDecl::Create( Inherited ? 1 : 0, ES.getExpr() ? 1 : 0); return new (C, RD, Extra) CXXConstructorDecl(C, RD, StartLoc, NameInfo, T, TInfo, ES, isInline, - isImplicitlyDeclared, ConstexprKind, Inherited); + isImplicitlyDeclared, ConstexprKind, Inherited, + TrailingRequiresClause); } CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin() const { @@ -2600,19 +2612,22 @@ CXXDestructorDecl * CXXDestructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) CXXDestructorDecl(C, nullptr, SourceLocation(), DeclarationNameInfo(), - QualType(), nullptr, false, false, CSK_unspecified); + QualType(), nullptr, false, false, CSK_unspecified, + nullptr); } CXXDestructorDecl *CXXDestructorDecl::Create( ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind) { + bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, + Expr *TrailingRequiresClause) { assert(NameInfo.getName().getNameKind() == DeclarationName::CXXDestructorName && "Name must refer to a destructor"); return new (C, RD) CXXDestructorDecl(C, RD, StartLoc, NameInfo, T, TInfo, isInline, - isImplicitlyDeclared, ConstexprKind); + isImplicitlyDeclared, ConstexprKind, + TrailingRequiresClause); } void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) { @@ -2631,20 +2646,20 @@ CXXConversionDecl * CXXConversionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) CXXConversionDecl( C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, - false, ExplicitSpecifier(), CSK_unspecified, SourceLocation()); + false, ExplicitSpecifier(), CSK_unspecified, SourceLocation(), nullptr); } CXXConversionDecl *CXXConversionDecl::Create( ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isInline, ExplicitSpecifier ES, ConstexprSpecKind ConstexprKind, - SourceLocation EndLocation) { + SourceLocation EndLocation, Expr *TrailingRequiresClause) { assert(NameInfo.getName().getNameKind() == DeclarationName::CXXConversionFunctionName && "Name must refer to a conversion function"); return new (C, RD) CXXConversionDecl(C, RD, StartLoc, NameInfo, T, TInfo, isInline, ES, - ConstexprKind, EndLocation); + ConstexprKind, EndLocation, TrailingRequiresClause); } bool CXXConversionDecl::isLambdaToBlockPointerConversion() const { @@ -2796,6 +2811,36 @@ NamespaceAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { SourceLocation(), nullptr); } +void LifetimeExtendedTemporaryDecl::anchor() {} + +/// Retrieve the storage duration for the materialized temporary. +StorageDuration LifetimeExtendedTemporaryDecl::getStorageDuration() const { + const ValueDecl *ExtendingDecl = getExtendingDecl(); + if (!ExtendingDecl) + return SD_FullExpression; + // FIXME: This is not necessarily correct for a temporary materialized + // within a default initializer. + if (isa<FieldDecl>(ExtendingDecl)) + return SD_Automatic; + // FIXME: This only works because storage class specifiers are not allowed + // on decomposition declarations. + if (isa<BindingDecl>(ExtendingDecl)) + return ExtendingDecl->getDeclContext()->isFunctionOrMethod() ? SD_Automatic + : SD_Static; + return cast<VarDecl>(ExtendingDecl)->getStorageDuration(); +} + +APValue *LifetimeExtendedTemporaryDecl::getOrCreateValue(bool MayCreate) const { + assert(getStorageDuration() == SD_Static && + "don't need to cache the computed value for this temporary"); + if (MayCreate && !Value) { + Value = (new (getASTContext()) APValue); + getASTContext().addDestruction(Value); + } + assert(Value && "may not be null"); + return Value; +} + void UsingShadowDecl::anchor() {} UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC, diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index bf748fbab8e9..9a84e3c4a510 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -775,14 +775,12 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod( // ObjCMethodDecl //===----------------------------------------------------------------------===// -ObjCMethodDecl::ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc, - Selector SelInfo, QualType T, - TypeSourceInfo *ReturnTInfo, - DeclContext *contextDecl, bool isInstance, - bool isVariadic, bool isPropertyAccessor, - bool isImplicitlyDeclared, bool isDefined, - ImplementationControl impControl, - bool HasRelatedResultType) +ObjCMethodDecl::ObjCMethodDecl( + SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo, + QualType T, TypeSourceInfo *ReturnTInfo, DeclContext *contextDecl, + bool isInstance, bool isVariadic, bool isPropertyAccessor, + bool isSynthesizedAccessorStub, bool isImplicitlyDeclared, bool isDefined, + ImplementationControl impControl, bool HasRelatedResultType) : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), DeclContext(ObjCMethod), MethodDeclType(T), ReturnTInfo(ReturnTInfo), DeclEndLoc(endLoc) { @@ -793,6 +791,7 @@ ObjCMethodDecl::ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc, setInstanceMethod(isInstance); setVariadic(isVariadic); setPropertyAccessor(isPropertyAccessor); + setSynthesizedAccessorStub(isSynthesizedAccessorStub); setDefined(isDefined); setIsRedeclaration(false); setHasRedeclaration(false); @@ -810,12 +809,13 @@ ObjCMethodDecl *ObjCMethodDecl::Create( ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo, DeclContext *contextDecl, bool isInstance, bool isVariadic, - bool isPropertyAccessor, bool isImplicitlyDeclared, bool isDefined, - ImplementationControl impControl, bool HasRelatedResultType) { + bool isPropertyAccessor, bool isSynthesizedAccessorStub, + bool isImplicitlyDeclared, bool isDefined, ImplementationControl impControl, + bool HasRelatedResultType) { return new (C, contextDecl) ObjCMethodDecl( beginLoc, endLoc, SelInfo, T, ReturnTInfo, contextDecl, isInstance, - isVariadic, isPropertyAccessor, isImplicitlyDeclared, isDefined, - impControl, HasRelatedResultType); + isVariadic, isPropertyAccessor, isSynthesizedAccessorStub, + isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType); } ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) { @@ -823,6 +823,10 @@ ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) { Selector(), QualType(), nullptr, nullptr); } +bool ObjCMethodDecl::isDirectMethod() const { + return hasAttr<ObjCDirectAttr>(); +} + bool ObjCMethodDecl::isThisDeclarationADesignatedInitializer() const { return getMethodFamily() == OMF_init && hasAttr<ObjCDesignatedInitializerAttr>(); @@ -952,24 +956,32 @@ ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() { ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() { auto *CtxD = cast<Decl>(getDeclContext()); + const auto &Sel = getSelector(); if (auto *ImplD = dyn_cast<ObjCImplementationDecl>(CtxD)) { - if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface()) - if (ObjCMethodDecl *MD = IFD->getMethod(getSelector(), - isInstanceMethod())) + if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface()) { + // When the container is the ObjCImplementationDecl (the primary + // @implementation), then the canonical Decl is either in + // the class Interface, or in any of its extension. + // + // So when we don't find it in the ObjCInterfaceDecl, + // sift through extensions too. + if (ObjCMethodDecl *MD = IFD->getMethod(Sel, isInstanceMethod())) return MD; + for (auto *Ext : IFD->known_extensions()) + if (ObjCMethodDecl *MD = Ext->getMethod(Sel, isInstanceMethod())) + return MD; + } } else if (auto *CImplD = dyn_cast<ObjCCategoryImplDecl>(CtxD)) { if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl()) - if (ObjCMethodDecl *MD = CatD->getMethod(getSelector(), - isInstanceMethod())) + if (ObjCMethodDecl *MD = CatD->getMethod(Sel, isInstanceMethod())) return MD; } if (isRedeclaration()) { // It is possible that we have not done deserializing the ObjCMethod yet. ObjCMethodDecl *MD = - cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(), - isInstanceMethod()); + cast<ObjCContainerDecl>(CtxD)->getMethod(Sel, isInstanceMethod()); return MD ? MD : this; } @@ -1077,7 +1089,7 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const { QualType ObjCMethodDecl::getSelfType(ASTContext &Context, const ObjCInterfaceDecl *OID, bool &selfIsPseudoStrong, - bool &selfIsConsumed) { + bool &selfIsConsumed) const { QualType selfTy; selfIsPseudoStrong = false; selfIsConsumed = false; @@ -1306,6 +1318,11 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const { if (isPropertyAccessor()) { const auto *Container = cast<ObjCContainerDecl>(getParent()); + // For accessor stubs, go back to the interface. + if (auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container)) + if (isSynthesizedAccessorStub()) + Container = ImplDecl->getClassInterface(); + bool IsGetter = (NumArgs == 0); bool IsInstance = isInstanceMethod(); @@ -1358,6 +1375,15 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const { } } + assert(isSynthesizedAccessorStub() && "expected an accessor stub"); + for (const auto *Cat : ClassDecl->known_categories()) { + if (Cat == Container) + continue; + + if (const auto *Found = findMatchingProperty(Cat)) + return Found; + } + llvm_unreachable("Marked as a property accessor but no property found!"); } diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index 608b0b44072b..4cedcbed0644 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -108,8 +108,8 @@ namespace { void printTemplateParameters(const TemplateParameterList *Params, bool OmitTemplateKW = false); - void printTemplateArguments(const TemplateArgumentList &Args, - const TemplateParameterList *Params = nullptr); + void printTemplateArguments(llvm::ArrayRef<TemplateArgument> Args); + void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args); void prettyPrintAttributes(Decl *D); void prettyPrintPragmas(Decl *D); void printDeclType(QualType T, StringRef DeclName, bool Pack = false); @@ -625,21 +625,26 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (Policy.FullyQualifiedName) { Proto += D->getQualifiedNameAsString(); } else { + llvm::raw_string_ostream OS(Proto); if (!Policy.SuppressScope) { if (const NestedNameSpecifier *NS = D->getQualifier()) { - llvm::raw_string_ostream OS(Proto); NS->print(OS, Policy); } } - Proto += D->getNameInfo().getAsString(); + D->getNameInfo().printName(OS, Policy); } if (GuideDecl) Proto = GuideDecl->getDeducedTemplate()->getDeclName().getAsString(); - if (const TemplateArgumentList *TArgs = D->getTemplateSpecializationArgs()) { + if (D->isFunctionTemplateSpecialization()) { llvm::raw_string_ostream POut(Proto); DeclPrinter TArgPrinter(POut, SubPolicy, Context, Indentation); - TArgPrinter.printTemplateArguments(*TArgs); + const auto *TArgAsWritten = D->getTemplateSpecializationArgsAsWritten(); + if (TArgAsWritten && !Policy.PrintCanonicalTypes) + TArgPrinter.printTemplateArguments(TArgAsWritten->arguments()); + else if (const TemplateArgumentList *TArgs = + D->getTemplateSpecializationArgs()) + TArgPrinter.printTemplateArguments(TArgs->asArray()); } QualType Ty = D->getType(); @@ -735,6 +740,11 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { Proto.clear(); } Out << Proto; + + if (Expr *TrailingRequiresClause = D->getTrailingRequiresClause()) { + Out << " requires "; + TrailingRequiresClause->printPretty(Out, nullptr, SubPolicy, Indentation); + } } else { Ty.print(Out, Policy, Proto); } @@ -957,10 +967,15 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { if (D->getIdentifier()) { Out << ' ' << *D; - if (auto S = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) - printTemplateArguments(S->getTemplateArgs(), S->getTemplateParameters()); - else if (auto S = dyn_cast<ClassTemplateSpecializationDecl>(D)) - printTemplateArguments(S->getTemplateArgs()); + if (auto S = dyn_cast<ClassTemplateSpecializationDecl>(D)) { + ArrayRef<TemplateArgument> Args = S->getTemplateArgs().asArray(); + if (!Policy.PrintCanonicalTypes) + if (const auto* TSI = S->getTypeAsWritten()) + if (const auto *TST = + dyn_cast<TemplateSpecializationType>(TSI->getType())) + Args = TST->template_arguments(); + printTemplateArguments(Args); + } } if (D->isCompleteDefinition()) { @@ -1001,19 +1016,12 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { const char *l; - switch (D->getLanguage()) { - case LinkageSpecDecl::lang_c: + if (D->getLanguage() == LinkageSpecDecl::lang_c) l = "C"; - break; - case LinkageSpecDecl::lang_cxx_14: - l = "C++14"; - break; - case LinkageSpecDecl::lang_cxx_11: - l = "C++11"; - break; - case LinkageSpecDecl::lang_cxx: + else { + assert(D->getLanguage() == LinkageSpecDecl::lang_cxx && + "unknown language in linkage specification"); l = "C++"; - break; } Out << "extern \"" << l << "\" "; @@ -1045,7 +1053,9 @@ void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params, if (auto TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { - if (TTP->wasDeclaredWithTypename()) + if (const TypeConstraint *TC = TTP->getTypeConstraint()) + TC->print(Out, Policy); + else if (TTP->wasDeclaredWithTypename()) Out << "typename"; else Out << "class"; @@ -1083,40 +1093,22 @@ void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params, Out << ' '; } -void DeclPrinter::printTemplateArguments(const TemplateArgumentList &Args, - const TemplateParameterList *Params) { +void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgument> Args) { Out << "<"; for (size_t I = 0, E = Args.size(); I < E; ++I) { - const TemplateArgument &A = Args[I]; if (I) Out << ", "; - if (Params) { - if (A.getKind() == TemplateArgument::Type) - if (auto T = A.getAsType()->getAs<TemplateTypeParmType>()) { - auto P = cast<TemplateTypeParmDecl>(Params->getParam(T->getIndex())); - Out << *P; - continue; - } - if (A.getKind() == TemplateArgument::Template) { - if (auto T = A.getAsTemplate().getAsTemplateDecl()) - if (auto TD = dyn_cast<TemplateTemplateParmDecl>(T)) { - auto P = cast<TemplateTemplateParmDecl>( - Params->getParam(TD->getIndex())); - Out << *P; - continue; - } - } - if (A.getKind() == TemplateArgument::Expression) { - if (auto E = dyn_cast<DeclRefExpr>(A.getAsExpr())) - if (auto N = dyn_cast<NonTypeTemplateParmDecl>(E->getDecl())) { - auto P = cast<NonTypeTemplateParmDecl>( - Params->getParam(N->getIndex())); - Out << *P; - continue; - } - } - } - A.print(Policy, Out); + Args[I].print(Policy, Out); + } + Out << ">"; +} + +void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgumentLoc> Args) { + Out << "<"; + for (size_t I = 0, E = Args.size(); I < E; ++I) { + if (I) + Out << ", "; + Args[I].getArgument().print(Policy, Out); } Out << ">"; } @@ -1469,6 +1461,11 @@ void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) { first = false; } + if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_direct) { + Out << (first ? "" : ", ") << "direct"; + first = false; + } + if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic) { Out << (first ? "" : ", ") << "nonatomic"; diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 7e013c6c54d8..95a2e26e0df8 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -43,35 +43,46 @@ using namespace clang; // TemplateParameterList Implementation //===----------------------------------------------------------------------===// -TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc, + +TemplateParameterList::TemplateParameterList(const ASTContext& C, + SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc, Expr *RequiresClause) : TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc), NumParams(Params.size()), ContainsUnexpandedParameterPack(false), - HasRequiresClause(static_cast<bool>(RequiresClause)) { + HasRequiresClause(RequiresClause != nullptr), + HasConstrainedParameters(false) { for (unsigned Idx = 0; Idx < NumParams; ++Idx) { NamedDecl *P = Params[Idx]; begin()[Idx] = P; - if (!P->isTemplateParameterPack()) { - if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) - if (NTTP->getType()->containsUnexpandedParameterPack()) - ContainsUnexpandedParameterPack = true; - - if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P)) - if (TTP->getTemplateParameters()->containsUnexpandedParameterPack()) - ContainsUnexpandedParameterPack = true; - - // FIXME: If a default argument contains an unexpanded parameter pack, the - // template parameter list does too. + bool IsPack = P->isTemplateParameterPack(); + if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) { + if (!IsPack && NTTP->getType()->containsUnexpandedParameterPack()) + ContainsUnexpandedParameterPack = true; + if (NTTP->hasPlaceholderTypeConstraint()) + HasConstrainedParameters = true; + } else if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P)) { + if (!IsPack && + TTP->getTemplateParameters()->containsUnexpandedParameterPack()) + ContainsUnexpandedParameterPack = true; + } else if (const TypeConstraint *TC = + cast<TemplateTypeParmDecl>(P)->getTypeConstraint()) { + if (TC->getImmediatelyDeclaredConstraint() + ->containsUnexpandedParameterPack()) + ContainsUnexpandedParameterPack = true; + HasConstrainedParameters = true; } + // FIXME: If a default argument contains an unexpanded parameter pack, the + // template parameter list does too. } - if (RequiresClause) { - *getTrailingObjects<Expr *>() = RequiresClause; + + if (HasRequiresClause) { if (RequiresClause->containsUnexpandedParameterPack()) ContainsUnexpandedParameterPack = true; + *getTrailingObjects<Expr *>() = RequiresClause; } } @@ -83,7 +94,7 @@ TemplateParameterList::Create(const ASTContext &C, SourceLocation TemplateLoc, void *Mem = C.Allocate(totalSizeToAlloc<NamedDecl *, Expr *>( Params.size(), RequiresClause ? 1u : 0u), alignof(TemplateParameterList)); - return new (Mem) TemplateParameterList(TemplateLoc, LAngleLoc, Params, + return new (Mem) TemplateParameterList(C, TemplateLoc, LAngleLoc, Params, RAngleLoc, RequiresClause); } @@ -91,11 +102,23 @@ unsigned TemplateParameterList::getMinRequiredArguments() const { unsigned NumRequiredArgs = 0; for (const NamedDecl *P : asArray()) { if (P->isTemplateParameterPack()) { - if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) + if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) { if (NTTP->isExpandedParameterPack()) { NumRequiredArgs += NTTP->getNumExpansionTypes(); continue; } + } else if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) { + if (TTP->isExpandedParameterPack()) { + NumRequiredArgs += TTP->getNumExpansionParameters(); + continue; + } + } else { + const auto *TP = cast<TemplateTemplateParmDecl>(P); + if (TP->isExpandedParameterPack()) { + NumRequiredArgs += TP->getNumExpansionTemplateParameters(); + continue; + } + } break; } @@ -140,14 +163,17 @@ static void AdoptTemplateParameterList(TemplateParameterList *Params, void TemplateParameterList:: getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const { - // TODO: Concepts: Collect immediately-introduced constraints. + if (HasConstrainedParameters) + for (const NamedDecl *Param : *this) + if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) + if (const auto *TC = TTP->getTypeConstraint()) + AC.push_back(TC->getImmediatelyDeclaredConstraint()); if (HasRequiresClause) AC.push_back(getRequiresClause()); } bool TemplateParameterList::hasAssociatedConstraints() const { - // TODO: Concepts: Regard immediately-introduced constraints. - return HasRequiresClause; + return HasRequiresClause || HasConstrainedParameters; } namespace clang { @@ -171,13 +197,18 @@ void TemplateDecl::anchor() {} void TemplateDecl:: getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const { - // TODO: Concepts: Append function trailing requires clause. TemplateParams->getAssociatedConstraints(AC); + if (auto *FD = dyn_cast_or_null<FunctionDecl>(getTemplatedDecl())) + if (const Expr *TRC = FD->getTrailingRequiresClause()) + AC.push_back(TRC); } bool TemplateDecl::hasAssociatedConstraints() const { - // TODO: Concepts: Regard function trailing requires clause. - return TemplateParams->hasAssociatedConstraints(); + if (TemplateParams->hasAssociatedConstraints()) + return true; + if (auto *FD = dyn_cast_or_null<FunctionDecl>(getTemplatedDecl())) + return FD->getTrailingRequiresClause(); + return false; } //===----------------------------------------------------------------------===// @@ -231,15 +262,16 @@ void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const { } } -template<class EntryType> +template<class EntryType, typename... ProfileArguments> typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType * RedeclarableTemplateDecl::findSpecializationImpl( - llvm::FoldingSetVector<EntryType> &Specs, ArrayRef<TemplateArgument> Args, - void *&InsertPos) { + llvm::FoldingSetVector<EntryType> &Specs, void *&InsertPos, + ProfileArguments&&... ProfileArgs) { using SETraits = SpecEntryTraits<EntryType>; llvm::FoldingSetNodeID ID; - EntryType::Profile(ID, Args, getASTContext()); + EntryType::Profile(ID, std::forward<ProfileArguments>(ProfileArgs)..., + getASTContext()); EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos); return Entry ? SETraits::getDecl(Entry)->getMostRecentDecl() : nullptr; } @@ -254,8 +286,8 @@ void RedeclarableTemplateDecl::addSpecializationImpl( #ifndef NDEBUG void *CorrectInsertPos; assert(!findSpecializationImpl(Specializations, - SETraits::getTemplateArgs(Entry), - CorrectInsertPos) && + CorrectInsertPos, + SETraits::getTemplateArgs(Entry)) && InsertPos == CorrectInsertPos && "given incorrect InsertPos for specialization"); #endif @@ -312,7 +344,7 @@ FunctionTemplateDecl::getSpecializations() const { FunctionDecl * FunctionTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos) { - return findSpecializationImpl(getSpecializations(), Args, InsertPos); + return findSpecializationImpl(getSpecializations(), InsertPos, Args); } void FunctionTemplateDecl::addSpecialization( @@ -418,7 +450,7 @@ ClassTemplateDecl::newCommon(ASTContext &C) const { ClassTemplateSpecializationDecl * ClassTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos) { - return findSpecializationImpl(getSpecializations(), Args, InsertPos); + return findSpecializationImpl(getSpecializations(), InsertPos, Args); } void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D, @@ -427,9 +459,48 @@ void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D, } ClassTemplatePartialSpecializationDecl * -ClassTemplateDecl::findPartialSpecialization(ArrayRef<TemplateArgument> Args, - void *&InsertPos) { - return findSpecializationImpl(getPartialSpecializations(), Args, InsertPos); +ClassTemplateDecl::findPartialSpecialization( + ArrayRef<TemplateArgument> Args, + TemplateParameterList *TPL, void *&InsertPos) { + return findSpecializationImpl(getPartialSpecializations(), InsertPos, Args, + TPL); +} + +static void ProfileTemplateParameterList(ASTContext &C, + llvm::FoldingSetNodeID &ID, const TemplateParameterList *TPL) { + const Expr *RC = TPL->getRequiresClause(); + ID.AddBoolean(RC != nullptr); + if (RC) + RC->Profile(ID, C, /*Canonical=*/true); + ID.AddInteger(TPL->size()); + for (NamedDecl *D : *TPL) { + if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) { + ID.AddInteger(0); + ID.AddBoolean(NTTP->isParameterPack()); + NTTP->getType().getCanonicalType().Profile(ID); + continue; + } + if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(D)) { + ID.AddInteger(1); + ID.AddBoolean(TTP->isParameterPack()); + // TODO: Concepts: profile type-constraints. + continue; + } + const auto *TTP = cast<TemplateTemplateParmDecl>(D); + ID.AddInteger(2); + ID.AddBoolean(TTP->isParameterPack()); + ProfileTemplateParameterList(C, ID, TTP->getTemplateParameters()); + } +} + +void +ClassTemplatePartialSpecializationDecl::Profile(llvm::FoldingSetNodeID &ID, + ArrayRef<TemplateArgument> TemplateArgs, TemplateParameterList *TPL, + ASTContext &Context) { + ID.AddInteger(TemplateArgs.size()); + for (const TemplateArgument &TemplateArg : TemplateArgs) + TemplateArg.Profile(ID, Context); + ProfileTemplateParameterList(Context, ID, TPL); } void ClassTemplateDecl::AddPartialSpecialization( @@ -513,9 +584,14 @@ TemplateTypeParmDecl * TemplateTypeParmDecl::Create(const ASTContext &C, DeclContext *DC, SourceLocation KeyLoc, SourceLocation NameLoc, unsigned D, unsigned P, IdentifierInfo *Id, - bool Typename, bool ParameterPack) { + bool Typename, bool ParameterPack, + bool HasTypeConstraint, + Optional<unsigned> NumExpanded) { auto *TTPDecl = - new (C, DC) TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename); + new (C, DC, + additionalSizeToAlloc<TypeConstraint>(HasTypeConstraint ? 1 : 0)) + TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename, + HasTypeConstraint, NumExpanded); QualType TTPType = C.getTemplateTypeParmType(D, P, ParameterPack, TTPDecl); TTPDecl->setTypeForDecl(TTPType.getTypePtr()); return TTPDecl; @@ -524,7 +600,17 @@ TemplateTypeParmDecl::Create(const ASTContext &C, DeclContext *DC, TemplateTypeParmDecl * TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { return new (C, ID) TemplateTypeParmDecl(nullptr, SourceLocation(), - SourceLocation(), nullptr, false); + SourceLocation(), nullptr, false, + false, None); +} + +TemplateTypeParmDecl * +TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, unsigned ID, + bool HasTypeConstraint) { + return new (C, ID, + additionalSizeToAlloc<TypeConstraint>(HasTypeConstraint ? 1 : 0)) + TemplateTypeParmDecl(nullptr, SourceLocation(), SourceLocation(), + nullptr, false, HasTypeConstraint, None); } SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const { @@ -557,6 +643,20 @@ bool TemplateTypeParmDecl::isParameterPack() const { return getTypeForDecl()->castAs<TemplateTypeParmType>()->isParameterPack(); } +void TemplateTypeParmDecl::setTypeConstraint(NestedNameSpecifierLoc NNS, + DeclarationNameInfo NameInfo, NamedDecl *FoundDecl, ConceptDecl *CD, + const ASTTemplateArgumentListInfo *ArgsAsWritten, + Expr *ImmediatelyDeclaredConstraint) { + assert(HasTypeConstraint && + "HasTypeConstraint=true must be passed at construction in order to " + "call setTypeConstraint"); + assert(!TypeConstraintInitialized && + "TypeConstraint was already initialized!"); + new (getTrailingObjects<TypeConstraint>()) TypeConstraint(NNS, NameInfo, + FoundDecl, CD, ArgsAsWritten, ImmediatelyDeclaredConstraint); + TypeConstraintInitialized = true; +} + //===----------------------------------------------------------------------===// // NonTypeTemplateParmDecl Method Implementations //===----------------------------------------------------------------------===// @@ -1035,7 +1135,7 @@ VarTemplateDecl::newCommon(ASTContext &C) const { VarTemplateSpecializationDecl * VarTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos) { - return findSpecializationImpl(getSpecializations(), Args, InsertPos); + return findSpecializationImpl(getSpecializations(), InsertPos, Args); } void VarTemplateDecl::AddSpecialization(VarTemplateSpecializationDecl *D, @@ -1045,8 +1145,19 @@ void VarTemplateDecl::AddSpecialization(VarTemplateSpecializationDecl *D, VarTemplatePartialSpecializationDecl * VarTemplateDecl::findPartialSpecialization(ArrayRef<TemplateArgument> Args, - void *&InsertPos) { - return findSpecializationImpl(getPartialSpecializations(), Args, InsertPos); + TemplateParameterList *TPL, void *&InsertPos) { + return findSpecializationImpl(getPartialSpecializations(), InsertPos, Args, + TPL); +} + +void +VarTemplatePartialSpecializationDecl::Profile(llvm::FoldingSetNodeID &ID, + ArrayRef<TemplateArgument> TemplateArgs, TemplateParameterList *TPL, + ASTContext &Context) { + ID.AddInteger(TemplateArgs.size()); + for (const TemplateArgument &TemplateArg : TemplateArgs) + TemplateArg.Profile(ID, Context); + ProfileTemplateParameterList(Context, ID, TPL); } void VarTemplateDecl::AddPartialSpecialization( @@ -1200,7 +1311,8 @@ createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) { // typename T auto *T = TemplateTypeParmDecl::Create( C, DC, SourceLocation(), SourceLocation(), /*Depth=*/1, /*Position=*/0, - /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false); + /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false, + /*HasTypeConstraint=*/false); T->setImplicit(true); // T ...Ints @@ -1225,7 +1337,8 @@ createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) { // typename T auto *TemplateTypeParm = TemplateTypeParmDecl::Create( C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1, - /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false); + /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false, + /*HasTypeConstraint=*/false); TemplateTypeParm->setImplicit(true); // T N @@ -1253,7 +1366,8 @@ createTypePackElementParameterList(const ASTContext &C, DeclContext *DC) { // typename ...T auto *Ts = TemplateTypeParmDecl::Create( C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1, - /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/true); + /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/true, + /*HasTypeConstraint=*/false); Ts->setImplicit(true); // template <std::size_t Index, typename ...T> @@ -1283,3 +1397,15 @@ BuiltinTemplateDecl::BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC, : TemplateDecl(BuiltinTemplate, DC, SourceLocation(), Name, createBuiltinTemplateParameterList(C, DC, BTK)), BTK(BTK) {} + +void TypeConstraint::print(llvm::raw_ostream &OS, PrintingPolicy Policy) const { + if (NestedNameSpec) + NestedNameSpec.getNestedNameSpecifier()->print(OS, Policy); + ConceptName.printName(OS, Policy); + if (hasExplicitTemplateArgs()) { + OS << "<"; + for (auto &ArgLoc : ArgsAsWritten->arguments()) + ArgLoc.getArgument().print(Policy, OS); + OS << ">"; + } +}
\ No newline at end of file diff --git a/clang/lib/AST/DeclarationName.cpp b/clang/lib/AST/DeclarationName.cpp index fe69c71aa3dd..4eb11bc57e52 100644 --- a/clang/lib/AST/DeclarationName.cpp +++ b/clang/lib/AST/DeclarationName.cpp @@ -134,7 +134,8 @@ static void printCXXConstructorDestructorName(QualType ClassType, ClassType.print(OS, Policy); } -void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) { +void DeclarationName::print(raw_ostream &OS, + const PrintingPolicy &Policy) const { switch (getNameKind()) { case DeclarationName::Identifier: if (const IdentifierInfo *II = getAsIdentifierInfo()) @@ -447,11 +448,17 @@ bool DeclarationNameInfo::isInstantiationDependent() const { std::string DeclarationNameInfo::getAsString() const { std::string Result; llvm::raw_string_ostream OS(Result); - printName(OS); + OS << *this; return OS.str(); } -void DeclarationNameInfo::printName(raw_ostream &OS) const { +raw_ostream &clang::operator<<(raw_ostream &OS, DeclarationNameInfo DNInfo) { + LangOptions LO; + DNInfo.printName(OS, PrintingPolicy(LangOptions())); + return OS; +} + +void DeclarationNameInfo::printName(raw_ostream &OS, PrintingPolicy Policy) const { switch (Name.getNameKind()) { case DeclarationName::Identifier: case DeclarationName::ObjCZeroArgSelector: @@ -461,7 +468,7 @@ void DeclarationNameInfo::printName(raw_ostream &OS) const { case DeclarationName::CXXLiteralOperatorName: case DeclarationName::CXXUsingDirective: case DeclarationName::CXXDeductionGuideName: - OS << Name; + Name.print(OS, Policy); return; case DeclarationName::CXXConstructorName: @@ -473,13 +480,11 @@ void DeclarationNameInfo::printName(raw_ostream &OS) const { else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) OS << "operator "; LangOptions LO; - LO.CPlusPlus = true; - LO.Bool = true; - PrintingPolicy PP(LO); - PP.SuppressScope = true; - OS << TInfo->getType().getAsString(PP); + Policy.adjustForCPlusPlus(); + Policy.SuppressScope = true; + OS << TInfo->getType().getAsString(Policy); } else - OS << Name; + Name.print(OS, Policy); return; } llvm_unreachable("Unexpected declaration name kind"); diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 3438c3aadc6b..73ddbc62482d 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -49,7 +49,7 @@ const Expr *Expr::getBestDynamicClassTypeExpr() const { // Step into initializer for materialized temporaries. if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) { - E = MTE->GetTemporaryExpr(); + E = MTE->getSubExpr(); continue; } @@ -127,11 +127,7 @@ const Expr *Expr::skipRValueSubobjectAdjustments( return E; } -/// isKnownToHaveBooleanValue - Return true if this is an integer expression -/// that is known to return 0 or 1. This happens for _Bool/bool expressions -/// but also int expressions which are produced by things like comparisons in -/// C. -bool Expr::isKnownToHaveBooleanValue() const { +bool Expr::isKnownToHaveBooleanValue(bool Semantic) const { const Expr *E = IgnoreParens(); // If this value has _Bool type, it is obvious 0/1. @@ -142,7 +138,7 @@ bool Expr::isKnownToHaveBooleanValue() const { if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) { switch (UO->getOpcode()) { case UO_Plus: - return UO->getSubExpr()->isKnownToHaveBooleanValue(); + return UO->getSubExpr()->isKnownToHaveBooleanValue(Semantic); case UO_LNot: return true; default: @@ -152,8 +148,9 @@ bool Expr::isKnownToHaveBooleanValue() const { // Only look through implicit casts. If the user writes // '(int) (a && b)' treat it as an arbitrary int. + // FIXME: Should we look through any cast expression in !Semantic mode? if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) - return CE->getSubExpr()->isKnownToHaveBooleanValue(); + return CE->getSubExpr()->isKnownToHaveBooleanValue(Semantic); if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) { switch (BO->getOpcode()) { @@ -172,24 +169,30 @@ bool Expr::isKnownToHaveBooleanValue() const { case BO_Xor: // Bitwise XOR operator. case BO_Or: // Bitwise OR operator. // Handle things like (x==2)|(y==12). - return BO->getLHS()->isKnownToHaveBooleanValue() && - BO->getRHS()->isKnownToHaveBooleanValue(); + return BO->getLHS()->isKnownToHaveBooleanValue(Semantic) && + BO->getRHS()->isKnownToHaveBooleanValue(Semantic); case BO_Comma: case BO_Assign: - return BO->getRHS()->isKnownToHaveBooleanValue(); + return BO->getRHS()->isKnownToHaveBooleanValue(Semantic); } } if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) - return CO->getTrueExpr()->isKnownToHaveBooleanValue() && - CO->getFalseExpr()->isKnownToHaveBooleanValue(); + return CO->getTrueExpr()->isKnownToHaveBooleanValue(Semantic) && + CO->getFalseExpr()->isKnownToHaveBooleanValue(Semantic); if (isa<ObjCBoolLiteralExpr>(E)) return true; if (const auto *OVE = dyn_cast<OpaqueValueExpr>(E)) - return OVE->getSourceExpr()->isKnownToHaveBooleanValue(); + return OVE->getSourceExpr()->isKnownToHaveBooleanValue(Semantic); + + if (const FieldDecl *FD = E->getSourceBitField()) + if (!Semantic && FD->getType()->isUnsignedIntegerType() && + !FD->getBitWidth()->isValueDependent() && + FD->getBitWidthValue(FD->getASTContext()) == 1) + return true; return false; } @@ -1675,6 +1678,15 @@ MemberExpr *MemberExpr::Create( MemberExpr *E = new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, MemberDecl, NameInfo, T, VK, OK, NOUR); + if (isa<FieldDecl>(MemberDecl)) { + DeclContext *DC = MemberDecl->getDeclContext(); + // dyn_cast_or_null is used to handle objC variables which do not + // have a declaration context. + CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(DC); + if (RD && RD->isDependentContext() && RD->isCurrentInstantiation(DC)) + E->setTypeDependent(T->isDependentType()); + } + if (HasQualOrFound) { // FIXME: Wrong. We should be looking at the member declaration we found. if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()->isDependent()) { @@ -1811,7 +1823,7 @@ bool CastExpr::CastConsistency() const { auto Ty = getType(); auto SETy = getSubExpr()->getType(); assert(getValueKindForType(Ty) == Expr::getValueKindForType(SETy)); - if (/*isRValue()*/ !Ty->getPointeeType().isNull()) { + if (isRValue()) { Ty = Ty->getPointeeType(); SETy = SETy->getPointeeType(); } @@ -1891,7 +1903,7 @@ namespace { const Expr *skipImplicitTemporary(const Expr *E) { // Skip through reference binding to temporary. if (auto *Materialize = dyn_cast<MaterializeTemporaryExpr>(E)) - E = Materialize->GetTemporaryExpr(); + E = Materialize->getSubExpr(); // Skip any temporary bindings; they're implicit. if (auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E)) @@ -2721,8 +2733,9 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, case CXXDeleteExprClass: return false; case MaterializeTemporaryExprClass: - return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr() - ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); + return cast<MaterializeTemporaryExpr>(this) + ->getSubExpr() + ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); case CXXBindTemporaryExprClass: return cast<CXXBindTemporaryExpr>(this)->getSubExpr() ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); @@ -2746,8 +2759,8 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const { case ImplicitCastExprClass: return cast<ImplicitCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx); case MaterializeTemporaryExprClass: - return cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr() - ->isOBJCGCCandidate(Ctx); + return cast<MaterializeTemporaryExpr>(E)->getSubExpr()->isOBJCGCCandidate( + Ctx); case CStyleCastExprClass: return cast<CStyleCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx); case DeclRefExprClass: { @@ -2822,7 +2835,7 @@ static Expr *IgnoreImpCastsExtraSingleStep(Expr *E) { return SubE; if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) - return MTE->GetTemporaryExpr(); + return MTE->getSubExpr(); if (auto *NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) return NTTP->getReplacement(); @@ -2838,7 +2851,7 @@ static Expr *IgnoreCastsSingleStep(Expr *E) { return FE->getSubExpr(); if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) - return MTE->GetTemporaryExpr(); + return MTE->getSubExpr(); if (auto *NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) return NTTP->getReplacement(); @@ -2872,7 +2885,7 @@ static Expr *IgnoreImplicitSingleStep(Expr *E) { return SubE; if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) - return MTE->GetTemporaryExpr(); + return MTE->getSubExpr(); if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(E)) return BTE->getSubExpr(); @@ -2880,6 +2893,13 @@ static Expr *IgnoreImplicitSingleStep(Expr *E) { return E; } +static Expr *IgnoreImplicitAsWrittenSingleStep(Expr *E) { + if (auto *ICE = dyn_cast<ImplicitCastExpr>(E)) + return ICE->getSubExprAsWritten(); + + return IgnoreImplicitSingleStep(E); +} + static Expr *IgnoreParensSingleStep(Expr *E) { if (auto *PE = dyn_cast<ParenExpr>(E)) return PE->getSubExpr(); @@ -2959,6 +2979,10 @@ Expr *Expr::IgnoreImplicit() { return IgnoreExprNodes(this, IgnoreImplicitSingleStep); } +Expr *Expr::IgnoreImplicitAsWritten() { + return IgnoreExprNodes(this, IgnoreImplicitAsWrittenSingleStep); +} + Expr *Expr::IgnoreParens() { return IgnoreExprNodes(this, IgnoreParensSingleStep); } @@ -2996,10 +3020,38 @@ Expr *Expr::IgnoreParenNoopCasts(const ASTContext &Ctx) { }); } +Expr *Expr::IgnoreUnlessSpelledInSource() { + Expr *E = this; + + Expr *LastE = nullptr; + while (E != LastE) { + LastE = E; + E = E->IgnoreParenImpCasts(); + + auto SR = E->getSourceRange(); + + if (auto *C = dyn_cast<CXXConstructExpr>(E)) { + if (C->getNumArgs() == 1) { + Expr *A = C->getArg(0); + if (A->getSourceRange() == SR || !isa<CXXTemporaryObjectExpr>(C)) + E = A; + } + } + + if (auto *C = dyn_cast<CXXMemberCallExpr>(E)) { + Expr *ExprNode = C->getImplicitObjectArgument()->IgnoreParenImpCasts(); + if (ExprNode->getSourceRange() == SR) + E = ExprNode; + } + } + + return E; +} + bool Expr::isDefaultArgument() const { const Expr *E = this; if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E)) - E = M->GetTemporaryExpr(); + E = M->getSubExpr(); while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) E = ICE->getSubExprAsWritten(); @@ -3011,7 +3063,7 @@ bool Expr::isDefaultArgument() const { /// expressions. static const Expr *skipTemporaryBindingsNoOpCastsAndParens(const Expr *E) { if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E)) - E = M->GetTemporaryExpr(); + E = M->getSubExpr(); while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { if (ICE->getCastKind() == CK_NoOp) @@ -3106,7 +3158,7 @@ bool Expr::isImplicitCXXThis() const { if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E)) { - E = M->GetTemporaryExpr(); + E = M->getSubExpr(); continue; } @@ -3283,8 +3335,9 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, break; } case MaterializeTemporaryExprClass: - return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr() - ->isConstantInitializer(Ctx, false, Culprit); + return cast<MaterializeTemporaryExpr>(this) + ->getSubExpr() + ->isConstantInitializer(Ctx, false, Culprit); case SubstNonTypeTemplateParmExprClass: return cast<SubstNonTypeTemplateParmExpr>(this)->getReplacement() @@ -3751,7 +3804,7 @@ Expr::isNullPointerConstant(ASTContext &Ctx, return NPCK_GNUNull; } else if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(this)) { - return M->GetTemporaryExpr()->isNullPointerConstant(Ctx, NPC); + return M->getSubExpr()->isNullPointerConstant(Ctx, NPC); } else if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(this)) { if (const Expr *Source = OVE->getSourceExpr()) return Source->isNullPointerConstant(Ctx, NPC); @@ -4460,7 +4513,7 @@ const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) { if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(e)) e = ewc->getSubExpr(); if (const MaterializeTemporaryExpr *m = dyn_cast<MaterializeTemporaryExpr>(e)) - e = m->GetTemporaryExpr(); + e = m->getSubExpr(); e = cast<CXXConstructExpr>(e)->getArg(0); while (const ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e)) e = ice->getSubExpr(); @@ -4598,6 +4651,8 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) { case AO__c11_atomic_fetch_and: case AO__c11_atomic_fetch_or: case AO__c11_atomic_fetch_xor: + case AO__c11_atomic_fetch_max: + case AO__c11_atomic_fetch_min: case AO__atomic_fetch_add: case AO__atomic_fetch_sub: case AO__atomic_fetch_and: @@ -4610,6 +4665,8 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) { case AO__atomic_or_fetch: case AO__atomic_xor_fetch: case AO__atomic_nand_fetch: + case AO__atomic_min_fetch: + case AO__atomic_max_fetch: case AO__atomic_fetch_min: case AO__atomic_fetch_max: return 3; diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 904928bdf286..422227d787b1 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -107,7 +107,7 @@ CXXRewrittenBinaryOperator::getDecomposedForm() const { return Result; // Otherwise, we expect a <=> to now be on the LHS. - E = Result.LHS->IgnoreImplicit(); + E = Result.LHS->IgnoreImplicitAsWritten(); if (auto *BO = dyn_cast<BinaryOperator>(E)) { assert(BO->getOpcode() == BO_Cmp); Result.LHS = BO->getLHS(); @@ -1653,7 +1653,23 @@ FunctionParmPackExpr::CreateEmpty(const ASTContext &Context, FunctionParmPackExpr(QualType(), nullptr, SourceLocation(), 0, nullptr); } -void MaterializeTemporaryExpr::setExtendingDecl(const ValueDecl *ExtendedBy, +MaterializeTemporaryExpr::MaterializeTemporaryExpr( + QualType T, Expr *Temporary, bool BoundToLvalueReference, + LifetimeExtendedTemporaryDecl *MTD) + : Expr(MaterializeTemporaryExprClass, T, + BoundToLvalueReference ? VK_LValue : VK_XValue, OK_Ordinary, + Temporary->isTypeDependent(), Temporary->isValueDependent(), + Temporary->isInstantiationDependent(), + Temporary->containsUnexpandedParameterPack()) { + if (MTD) { + State = MTD; + MTD->ExprWithTemporary = Temporary; + return; + } + State = Temporary; +} + +void MaterializeTemporaryExpr::setExtendingDecl(ValueDecl *ExtendedBy, unsigned ManglingNumber) { // We only need extra state if we have to remember more than just the Stmt. if (!ExtendedBy) @@ -1661,13 +1677,11 @@ void MaterializeTemporaryExpr::setExtendingDecl(const ValueDecl *ExtendedBy, // We may need to allocate extra storage for the mangling number and the // extended-by ValueDecl. - if (!State.is<ExtraState *>()) { - auto *ES = new (ExtendedBy->getASTContext()) ExtraState; - ES->Temporary = State.get<Stmt *>(); - State = ES; - } + if (!State.is<LifetimeExtendedTemporaryDecl *>()) + State = LifetimeExtendedTemporaryDecl::Create( + cast<Expr>(State.get<Stmt *>()), ExtendedBy, ManglingNumber); - auto ES = State.get<ExtraState *>(); + auto ES = State.get<LifetimeExtendedTemporaryDecl *>(); ES->ExtendingDecl = ExtendedBy; ES->ManglingNumber = ManglingNumber; } @@ -1751,44 +1765,42 @@ CUDAKernelCallExpr *CUDAKernelCallExpr::CreateEmpty(const ASTContext &Ctx, return new (Mem) CUDAKernelCallExpr(NumArgs, Empty); } -ConceptSpecializationExpr::ConceptSpecializationExpr(ASTContext &C, +ConceptSpecializationExpr::ConceptSpecializationExpr(const ASTContext &C, NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, - SourceLocation ConceptNameLoc, NamedDecl *FoundDecl, + DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, ConceptDecl *NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten, - ArrayRef<TemplateArgument> ConvertedArgs, Optional<bool> IsSatisfied) + ArrayRef<TemplateArgument> ConvertedArgs, + const ConstraintSatisfaction *Satisfaction) : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary, /*TypeDependent=*/false, // All the flags below are set in setTemplateArguments. - /*ValueDependent=*/!IsSatisfied.hasValue(), - /*InstantiationDependent=*/false, + /*ValueDependent=*/!Satisfaction, /*InstantiationDependent=*/false, /*ContainsUnexpandedParameterPacks=*/false), - NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc), - ConceptNameLoc(ConceptNameLoc), FoundDecl(FoundDecl), - NamedConcept(NamedConcept, IsSatisfied ? *IsSatisfied : true), - NumTemplateArgs(ConvertedArgs.size()) { - - setTemplateArguments(ArgsAsWritten, ConvertedArgs); + ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl, + NamedConcept, ArgsAsWritten), + NumTemplateArgs(ConvertedArgs.size()), + Satisfaction(Satisfaction ? + ASTConstraintSatisfaction::Create(C, *Satisfaction) : + nullptr) { + setTemplateArguments(ConvertedArgs); } ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs) - : Expr(ConceptSpecializationExprClass, Empty), + : Expr(ConceptSpecializationExprClass, Empty), ConceptReference(), NumTemplateArgs(NumTemplateArgs) { } void ConceptSpecializationExpr::setTemplateArguments( - const ASTTemplateArgumentListInfo *ArgsAsWritten, ArrayRef<TemplateArgument> Converted) { assert(Converted.size() == NumTemplateArgs); - assert(!this->ArgsAsWritten && "setTemplateArguments can only be used once"); - this->ArgsAsWritten = ArgsAsWritten; std::uninitialized_copy(Converted.begin(), Converted.end(), getTrailingObjects<TemplateArgument>()); bool IsInstantiationDependent = false; bool ContainsUnexpandedParameterPack = false; - for (const TemplateArgumentLoc& LocInfo : ArgsAsWritten->arguments()) { - if (LocInfo.getArgument().isInstantiationDependent()) + for (const TemplateArgument& Arg : Converted) { + if (Arg.isInstantiationDependent()) IsInstantiationDependent = true; - if (LocInfo.getArgument().containsUnexpandedParameterPack()) + if (Arg.containsUnexpandedParameterPack()) ContainsUnexpandedParameterPack = true; if (ContainsUnexpandedParameterPack && IsInstantiationDependent) break; @@ -1806,20 +1818,21 @@ void ConceptSpecializationExpr::setTemplateArguments( } ConceptSpecializationExpr * -ConceptSpecializationExpr::Create(ASTContext &C, NestedNameSpecifierLoc NNS, +ConceptSpecializationExpr::Create(const ASTContext &C, + NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, - SourceLocation ConceptNameLoc, + DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, ConceptDecl *NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten, ArrayRef<TemplateArgument> ConvertedArgs, - Optional<bool> IsSatisfied) { + const ConstraintSatisfaction *Satisfaction) { void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>( ConvertedArgs.size())); return new (Buffer) ConceptSpecializationExpr(C, NNS, TemplateKWLoc, - ConceptNameLoc, FoundDecl, + ConceptNameInfo, FoundDecl, NamedConcept, ArgsAsWritten, - ConvertedArgs, IsSatisfied); + ConvertedArgs, Satisfaction); } ConceptSpecializationExpr * diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 42c746e60285..c4b27b5d1daa 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -32,8 +32,6 @@ // //===----------------------------------------------------------------------===// -#include <cstring> -#include <functional> #include "Interp/Context.h" #include "Interp/Frame.h" #include "Interp/State.h" @@ -41,6 +39,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ASTLambda.h" +#include "clang/AST/Attr.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/CharUnits.h" #include "clang/AST/CurrentSourceLocExprScope.h" @@ -57,6 +56,8 @@ #include "llvm/ADT/SmallBitVector.h" #include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/raw_ostream.h" +#include <cstring> +#include <functional> #define DEBUG_TYPE "exprconstant" @@ -107,7 +108,7 @@ namespace { dyn_cast<MaterializeTemporaryExpr>(Base)) { SmallVector<const Expr *, 2> CommaLHSs; SmallVector<SubobjectAdjustment, 2> Adjustments; - const Expr *Temp = MTE->GetTemporaryExpr(); + const Expr *Temp = MTE->getSubExpr(); const Expr *Inner = Temp->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); // Keep any cv-qualifiers from the reference if we generated a temporary @@ -763,11 +764,8 @@ namespace { /// we will evaluate. unsigned StepsLeft; - /// Force the use of the experimental new constant interpreter, bailing out - /// with an error if a feature is not supported. - bool ForceNewConstInterp; - - /// Enable the experimental new constant interpreter. + /// Enable the experimental new constant interpreter. If an expression is + /// not supported by the interpreter, an error is triggered. bool EnableNewConstInterp; /// BottomFrame - The frame in which evaluation started. This must be @@ -921,10 +919,8 @@ namespace { EvalInfo(const ASTContext &C, Expr::EvalStatus &S, EvaluationMode Mode) : Ctx(const_cast<ASTContext &>(C)), EvalStatus(S), CurrentCall(nullptr), CallStackDepth(0), NextCallIndex(1), - StepsLeft(getLangOpts().ConstexprStepLimit), - ForceNewConstInterp(getLangOpts().ForceNewConstInterp), - EnableNewConstInterp(ForceNewConstInterp || - getLangOpts().EnableNewConstInterp), + StepsLeft(C.getLangOpts().ConstexprStepLimit), + EnableNewConstInterp(C.getLangOpts().EnableNewConstInterp), BottomFrame(*this, SourceLocation(), nullptr, nullptr, nullptr), EvaluatingDecl((const ValueDecl *)nullptr), EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false), @@ -1039,10 +1035,13 @@ namespace { /// cleanups would have had a side-effect, note that as an unmodeled /// side-effect and return false. Otherwise, return true. bool discardCleanups() { - for (Cleanup &C : CleanupStack) - if (C.hasSideEffect()) - if (!noteSideEffect()) - return false; + for (Cleanup &C : CleanupStack) { + if (C.hasSideEffect() && !noteSideEffect()) { + CleanupStack.clear(); + return false; + } + } + CleanupStack.clear(); return true; } @@ -2072,7 +2071,7 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, return false; } - APValue *V = Info.Ctx.getMaterializedTemporaryValue(MTE, false); + APValue *V = MTE->getOrCreateValue(false); assert(V && "evasluation result refers to uninitialised temporary"); if (!CheckEvaluationResult(CheckEvaluationResultKind::ConstantExpression, Info, MTE->getExprLoc(), TempType, *V, @@ -3676,7 +3675,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, return CompleteObject(); } - BaseVal = Info.Ctx.getMaterializedTemporaryValue(MTE, false); + BaseVal = MTE->getOrCreateValue(false); assert(BaseVal && "got reference to unevaluated temporary"); } else { if (!IsAccess) @@ -5333,9 +5332,16 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr, if (!FD || FD->getType()->isReferenceType()) break; - // ... and also contains A.B if B names a union member - if (FD->getParent()->isUnion()) - UnionPathLengths.push_back({PathLength - 1, FD}); + // ... and also contains A.B if B names a union member ... + if (FD->getParent()->isUnion()) { + // ... of a non-class, non-array type, or of a class type with a + // trivial default constructor that is not deleted, or an array of + // such types. + auto *RD = + FD->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); + if (!RD || RD->hasTrivialDefaultConstructor()) + UnionPathLengths.push_back({PathLength - 1, FD}); + } E = ME->getBase(); --PathLength; @@ -6824,6 +6830,36 @@ public: return StmtVisitorTy::Visit(Source); } + bool VisitPseudoObjectExpr(const PseudoObjectExpr *E) { + for (const Expr *SemE : E->semantics()) { + if (auto *OVE = dyn_cast<OpaqueValueExpr>(SemE)) { + // FIXME: We can't handle the case where an OpaqueValueExpr is also the + // result expression: there could be two different LValues that would + // refer to the same object in that case, and we can't model that. + if (SemE == E->getResultExpr()) + return Error(E); + + // Unique OVEs get evaluated if and when we encounter them when + // emitting the rest of the semantic form, rather than eagerly. + if (OVE->isUnique()) + continue; + + LValue LV; + if (!Evaluate(Info.CurrentCall->createTemporary( + OVE, getStorageType(Info.Ctx, OVE), false, LV), + Info, OVE->getSourceExpr())) + return false; + } else if (SemE == E->getResultExpr()) { + if (!StmtVisitorTy::Visit(SemE)) + return false; + } else { + if (!EvaluateIgnoredValue(Info, SemE)) + return false; + } + } + return true; + } + bool VisitCallExpr(const CallExpr *E) { APValue Result; if (!handleCallExpr(E, Result, nullptr)) @@ -7044,6 +7080,31 @@ public: DerivedSuccess(Result, E); } + bool VisitExtVectorElementExpr(const ExtVectorElementExpr *E) { + APValue Val; + if (!Evaluate(Val, Info, E->getBase())) + return false; + + if (Val.isVector()) { + SmallVector<uint32_t, 4> Indices; + E->getEncodedElementAccess(Indices); + if (Indices.size() == 1) { + // Return scalar. + return DerivedSuccess(Val.getVectorElt(Indices[0]), E); + } else { + // Construct new APValue vector. + SmallVector<APValue, 4> Elts; + for (unsigned I = 0; I < Indices.size(); ++I) { + Elts.push_back(Val.getVectorElt(Indices[I])); + } + APValue VecResult(Elts.data(), Indices.size()); + return DerivedSuccess(VecResult, E); + } + } + + return false; + } + bool VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: @@ -7082,6 +7143,13 @@ public: return false; return DerivedSuccess(DestValue, E); } + + case CK_AddressSpaceConversion: { + APValue Value; + if (!Evaluate(Value, Info, E->getSubExpr())) + return false; + return DerivedSuccess(Value, E); + } } return Error(E); @@ -7460,8 +7528,8 @@ bool LValueExprEvaluator::VisitMaterializeTemporaryExpr( // Walk through the expression to find the materialized temporary itself. SmallVector<const Expr *, 2> CommaLHSs; SmallVector<SubobjectAdjustment, 2> Adjustments; - const Expr *Inner = E->GetTemporaryExpr()-> - skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); + const Expr *Inner = + E->getSubExpr()->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); // If we passed any comma operators, evaluate their LHSs. for (unsigned I = 0, N = CommaLHSs.size(); I != N; ++I) @@ -7473,7 +7541,7 @@ bool LValueExprEvaluator::VisitMaterializeTemporaryExpr( // value for use outside this evaluation. APValue *Value; if (E->getStorageDuration() == SD_Static) { - Value = Info.Ctx.getMaterializedTemporaryValue(E, true); + Value = E->getOrCreateValue(true); *Value = APValue(); Result.set(E); } else { @@ -7856,6 +7924,11 @@ public: // either copied into the closure object's field that represents the '*this' // or refers to '*this'. if (isLambdaCallOperator(Info.CurrentCall->Callee)) { + // Ensure we actually have captured 'this'. (an error will have + // been previously reported if not). + if (!Info.CurrentCall->LambdaThisCaptureField) + return false; + // Update 'Result' to refer to the data member/field of the closure object // that represents the '*this' capture. if (!HandleLValueMember(Info, E, Result, @@ -8102,6 +8175,42 @@ static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E, return GetAlignOfType(Info, E->getType(), ExprKind); } +static CharUnits getBaseAlignment(EvalInfo &Info, const LValue &Value) { + if (const auto *VD = Value.Base.dyn_cast<const ValueDecl *>()) + return Info.Ctx.getDeclAlign(VD); + if (const auto *E = Value.Base.dyn_cast<const Expr *>()) + return GetAlignOfExpr(Info, E, UETT_AlignOf); + return GetAlignOfType(Info, Value.Base.getTypeInfoType(), UETT_AlignOf); +} + +/// Evaluate the value of the alignment argument to __builtin_align_{up,down}, +/// __builtin_is_aligned and __builtin_assume_aligned. +static bool getAlignmentArgument(const Expr *E, QualType ForType, + EvalInfo &Info, APSInt &Alignment) { + if (!EvaluateInteger(E, Alignment, Info)) + return false; + if (Alignment < 0 || !Alignment.isPowerOf2()) { + Info.FFDiag(E, diag::note_constexpr_invalid_alignment) << Alignment; + return false; + } + unsigned SrcWidth = Info.Ctx.getIntWidth(ForType); + APSInt MaxValue(APInt::getOneBitSet(SrcWidth, SrcWidth - 1)); + if (APSInt::compareValues(Alignment, MaxValue) > 0) { + Info.FFDiag(E, diag::note_constexpr_alignment_too_big) + << MaxValue << ForType << Alignment; + return false; + } + // Ensure both alignment and source value have the same bit width so that we + // don't assert when computing the resulting value. + APSInt ExtAlignment = + APSInt(Alignment.zextOrTrunc(SrcWidth), /*isUnsigned=*/true); + assert(APSInt::compareValues(Alignment, ExtAlignment) == 0 && + "Alignment should not be changed by ext/trunc"); + Alignment = ExtAlignment; + assert(Alignment.getBitWidth() == SrcWidth); + return true; +} + // To be clear: this happily visits unsupported builtins. Better name welcomed. bool PointerExprEvaluator::visitNonBuiltinCallExpr(const CallExpr *E) { if (ExprEvaluatorBaseTy::VisitCallExpr(E)) @@ -8140,7 +8249,8 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, LValue OffsetResult(Result); APSInt Alignment; - if (!EvaluateInteger(E->getArg(1), Alignment, Info)) + if (!getAlignmentArgument(E->getArg(1), E->getArg(0)->getType(), Info, + Alignment)) return false; CharUnits Align = CharUnits::fromQuantity(Alignment.getZExtValue()); @@ -8155,16 +8265,7 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, // If there is a base object, then it must have the correct alignment. if (OffsetResult.Base) { - CharUnits BaseAlignment; - if (const ValueDecl *VD = - OffsetResult.Base.dyn_cast<const ValueDecl*>()) { - BaseAlignment = Info.Ctx.getDeclAlign(VD); - } else if (const Expr *E = OffsetResult.Base.dyn_cast<const Expr *>()) { - BaseAlignment = GetAlignOfExpr(Info, E, UETT_AlignOf); - } else { - BaseAlignment = GetAlignOfType( - Info, OffsetResult.Base.getTypeInfoType(), UETT_AlignOf); - } + CharUnits BaseAlignment = getBaseAlignment(Info, OffsetResult); if (BaseAlignment < Align) { Result.Designator.setInvalid(); @@ -8193,6 +8294,43 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, return true; } + case Builtin::BI__builtin_align_up: + case Builtin::BI__builtin_align_down: { + if (!evaluatePointer(E->getArg(0), Result)) + return false; + APSInt Alignment; + if (!getAlignmentArgument(E->getArg(1), E->getArg(0)->getType(), Info, + Alignment)) + return false; + CharUnits BaseAlignment = getBaseAlignment(Info, Result); + CharUnits PtrAlign = BaseAlignment.alignmentAtOffset(Result.Offset); + // For align_up/align_down, we can return the same value if the alignment + // is known to be greater or equal to the requested value. + if (PtrAlign.getQuantity() >= Alignment) + return true; + + // The alignment could be greater than the minimum at run-time, so we cannot + // infer much about the resulting pointer value. One case is possible: + // For `_Alignas(32) char buf[N]; __builtin_align_down(&buf[idx], 32)` we + // can infer the correct index if the requested alignment is smaller than + // the base alignment so we can perform the computation on the offset. + if (BaseAlignment.getQuantity() >= Alignment) { + assert(Alignment.getBitWidth() <= 64 && + "Cannot handle > 64-bit address-space"); + uint64_t Alignment64 = Alignment.getZExtValue(); + CharUnits NewOffset = CharUnits::fromQuantity( + BuiltinOp == Builtin::BI__builtin_align_down + ? llvm::alignDown(Result.Offset.getQuantity(), Alignment64) + : llvm::alignTo(Result.Offset.getQuantity(), Alignment64)); + Result.adjustOffset(NewOffset - Result.Offset); + // TODO: diagnose out-of-bounds values/only allow for arrays? + return true; + } + // Otherwise, we cannot constant-evaluate the result. + Info.FFDiag(E->getArg(0), diag::note_constexpr_alignment_adjust) + << Alignment; + return false; + } case Builtin::BI__builtin_operator_new: return HandleOperatorNewCall(Info, E, Result); case Builtin::BI__builtin_launder: @@ -9021,7 +9159,7 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E, if (E->isElidable() && !ZeroInit) if (const MaterializeTemporaryExpr *ME = dyn_cast<MaterializeTemporaryExpr>(E->getArg(0))) - return Visit(ME->GetTemporaryExpr()); + return Visit(ME->getSubExpr()); if (ZeroInit && !ZeroInitialization(E, T)) return false; @@ -9240,6 +9378,7 @@ namespace { bool VisitUnaryImag(const UnaryOperator *E); // FIXME: Missing: unary -, unary ~, binary add/sub/mul/div, // binary comparisons, binary and/or/xor, + // conditional operator (for GNU conditional select), // shufflevector, ExtVectorElementExpr }; } // end anonymous namespace @@ -10170,7 +10309,7 @@ static QualType getObjectType(APValue::LValueBase B) { if (const ValueDecl *D = B.dyn_cast<const ValueDecl*>()) { if (const VarDecl *VD = dyn_cast<VarDecl>(D)) return VD->getType(); - } else if (const Expr *E = B.get<const Expr*>()) { + } else if (const Expr *E = B.dyn_cast<const Expr*>()) { if (isa<CompoundLiteralExpr>(E)) return E->getType(); } else if (B.is<TypeInfoLValue>()) { @@ -10491,6 +10630,33 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { return ExprEvaluatorBaseTy::VisitCallExpr(E); } +static bool getBuiltinAlignArguments(const CallExpr *E, EvalInfo &Info, + APValue &Val, APSInt &Alignment) { + QualType SrcTy = E->getArg(0)->getType(); + if (!getAlignmentArgument(E->getArg(1), SrcTy, Info, Alignment)) + return false; + // Even though we are evaluating integer expressions we could get a pointer + // argument for the __builtin_is_aligned() case. + if (SrcTy->isPointerType()) { + LValue Ptr; + if (!EvaluatePointer(E->getArg(0), Ptr, Info)) + return false; + Ptr.moveInto(Val); + } else if (!SrcTy->isIntegralOrEnumerationType()) { + Info.FFDiag(E->getArg(0)); + return false; + } else { + APSInt SrcInt; + if (!EvaluateInteger(E->getArg(0), SrcInt, Info)) + return false; + assert(SrcInt.getBitWidth() >= Alignment.getBitWidth() && + "Bit widths must be the same"); + Val = APValue(SrcInt); + } + assert(Val.hasValue()); + return true; +} + bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp) { switch (unsigned BuiltinOp = E->getBuiltinCallee()) { @@ -10533,6 +10699,66 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, return Success(Layout.size().getQuantity(), E); } + case Builtin::BI__builtin_is_aligned: { + APValue Src; + APSInt Alignment; + if (!getBuiltinAlignArguments(E, Info, Src, Alignment)) + return false; + if (Src.isLValue()) { + // If we evaluated a pointer, check the minimum known alignment. + LValue Ptr; + Ptr.setFrom(Info.Ctx, Src); + CharUnits BaseAlignment = getBaseAlignment(Info, Ptr); + CharUnits PtrAlign = BaseAlignment.alignmentAtOffset(Ptr.Offset); + // We can return true if the known alignment at the computed offset is + // greater than the requested alignment. + assert(PtrAlign.isPowerOfTwo()); + assert(Alignment.isPowerOf2()); + if (PtrAlign.getQuantity() >= Alignment) + return Success(1, E); + // If the alignment is not known to be sufficient, some cases could still + // be aligned at run time. However, if the requested alignment is less or + // equal to the base alignment and the offset is not aligned, we know that + // the run-time value can never be aligned. + if (BaseAlignment.getQuantity() >= Alignment && + PtrAlign.getQuantity() < Alignment) + return Success(0, E); + // Otherwise we can't infer whether the value is sufficiently aligned. + // TODO: __builtin_is_aligned(__builtin_align_{down,up{(expr, N), N) + // in cases where we can't fully evaluate the pointer. + Info.FFDiag(E->getArg(0), diag::note_constexpr_alignment_compute) + << Alignment; + return false; + } + assert(Src.isInt()); + return Success((Src.getInt() & (Alignment - 1)) == 0 ? 1 : 0, E); + } + case Builtin::BI__builtin_align_up: { + APValue Src; + APSInt Alignment; + if (!getBuiltinAlignArguments(E, Info, Src, Alignment)) + return false; + if (!Src.isInt()) + return Error(E); + APSInt AlignedVal = + APSInt((Src.getInt() + (Alignment - 1)) & ~(Alignment - 1), + Src.getInt().isUnsigned()); + assert(AlignedVal.getBitWidth() == Src.getInt().getBitWidth()); + return Success(AlignedVal, E); + } + case Builtin::BI__builtin_align_down: { + APValue Src; + APSInt Alignment; + if (!getBuiltinAlignArguments(E, Info, Src, Alignment)) + return false; + if (!Src.isInt()) + return Error(E); + APSInt AlignedVal = + APSInt(Src.getInt() & ~(Alignment - 1), Src.getInt().isUnsigned()); + assert(AlignedVal.getBitWidth() == Src.getInt().getBitWidth()); + return Success(AlignedVal, E); + } + case Builtin::BI__builtin_bswap16: case Builtin::BI__builtin_bswap32: case Builtin::BI__builtin_bswap64: { @@ -10583,8 +10809,24 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, return false; } - case Builtin::BI__builtin_is_constant_evaluated: + case Builtin::BI__builtin_is_constant_evaluated: { + const auto *Callee = Info.CurrentCall->getCallee(); + if (Info.InConstantContext && !Info.CheckingPotentialConstantExpression && + (Info.CallStackDepth == 1 || + (Info.CallStackDepth == 2 && Callee->isInStdNamespace() && + Callee->getIdentifier() && + Callee->getIdentifier()->isStr("is_constant_evaluated")))) { + // FIXME: Find a better way to avoid duplicated diagnostics. + if (Info.EvalStatus.Diag) + Info.report((Info.CallStackDepth == 1) ? E->getExprLoc() + : Info.CurrentCall->CallLoc, + diag::warn_is_constant_evaluated_always_true_constexpr) + << (Info.CallStackDepth == 1 ? "__builtin_is_constant_evaluated" + : "std::is_constant_evaluated"); + } + return Success(Info.InConstantContext, E); + } case Builtin::BI__builtin_ctz: case Builtin::BI__builtin_ctzl: @@ -11417,6 +11659,14 @@ public: } } }; + +enum class CmpResult { + Unequal, + Less, + Equal, + Greater, + Unordered, +}; } template <class SuccessCB, class AfterCB> @@ -11432,15 +11682,8 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, return false; }; - using CCR = ComparisonCategoryResult; - bool IsRelational = E->isRelationalOp(); + bool IsRelational = E->isRelationalOp() || E->getOpcode() == BO_Cmp; bool IsEquality = E->isEqualityOp(); - if (E->getOpcode() == BO_Cmp) { - const ComparisonCategoryInfo &CmpInfo = - Info.Ctx.CompCategories.getInfoForType(E->getType()); - IsRelational = CmpInfo.isOrdered(); - IsEquality = CmpInfo.isEquality(); - } QualType LHSTy = E->getLHS()->getType(); QualType RHSTy = E->getRHS()->getType(); @@ -11454,10 +11697,10 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, if (!EvaluateInteger(E->getRHS(), RHS, Info) || !LHSOK) return false; if (LHS < RHS) - return Success(CCR::Less, E); + return Success(CmpResult::Less, E); if (LHS > RHS) - return Success(CCR::Greater, E); - return Success(CCR::Equal, E); + return Success(CmpResult::Greater, E); + return Success(CmpResult::Equal, E); } if (LHSTy->isFixedPointType() || RHSTy->isFixedPointType()) { @@ -11470,10 +11713,10 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, if (!EvaluateFixedPointOrInteger(E->getRHS(), RHSFX, Info) || !LHSOK) return false; if (LHSFX < RHSFX) - return Success(CCR::Less, E); + return Success(CmpResult::Less, E); if (LHSFX > RHSFX) - return Success(CCR::Greater, E); - return Success(CCR::Equal, E); + return Success(CmpResult::Greater, E); + return Success(CmpResult::Equal, E); } if (LHSTy->isAnyComplexType() || RHSTy->isAnyComplexType()) { @@ -11509,12 +11752,12 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, APFloat::cmpResult CR_i = LHS.getComplexFloatImag().compare(RHS.getComplexFloatImag()); bool IsEqual = CR_r == APFloat::cmpEqual && CR_i == APFloat::cmpEqual; - return Success(IsEqual ? CCR::Equal : CCR::Nonequal, E); + return Success(IsEqual ? CmpResult::Equal : CmpResult::Unequal, E); } else { assert(IsEquality && "invalid complex comparison"); bool IsEqual = LHS.getComplexIntReal() == RHS.getComplexIntReal() && LHS.getComplexIntImag() == RHS.getComplexIntImag(); - return Success(IsEqual ? CCR::Equal : CCR::Nonequal, E); + return Success(IsEqual ? CmpResult::Equal : CmpResult::Unequal, E); } } @@ -11533,13 +11776,13 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, auto GetCmpRes = [&]() { switch (LHS.compare(RHS)) { case APFloat::cmpEqual: - return CCR::Equal; + return CmpResult::Equal; case APFloat::cmpLessThan: - return CCR::Less; + return CmpResult::Less; case APFloat::cmpGreaterThan: - return CCR::Greater; + return CmpResult::Greater; case APFloat::cmpUnordered: - return CCR::Unordered; + return CmpResult::Unordered; } llvm_unreachable("Unrecognised APFloat::cmpResult enum"); }; @@ -11561,8 +11804,10 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, if (!HasSameBase(LHSValue, RHSValue)) { // Inequalities and subtractions between unrelated pointers have // unspecified or undefined behavior. - if (!IsEquality) - return Error(E); + if (!IsEquality) { + Info.FFDiag(E, diag::note_constexpr_pointer_comparison_unspecified); + return false; + } // A constant address may compare equal to the address of a symbol. // The one exception is that address of an object cannot compare equal // to a null pointer constant. @@ -11592,7 +11837,7 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, if ((RHSValue.Base && isZeroSized(LHSValue)) || (LHSValue.Base && isZeroSized(RHSValue))) return Error(E); - return Success(CCR::Nonequal, E); + return Success(CmpResult::Unequal, E); } const CharUnits &LHSOffset = LHSValue.getLValueOffset(); @@ -11676,10 +11921,10 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, } if (CompareLHS < CompareRHS) - return Success(CCR::Less, E); + return Success(CmpResult::Less, E); if (CompareLHS > CompareRHS) - return Success(CCR::Greater, E); - return Success(CCR::Equal, E); + return Success(CmpResult::Greater, E); + return Success(CmpResult::Equal, E); } if (LHSTy->isMemberPointerType()) { @@ -11700,7 +11945,7 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, // null, they compare unequal. if (!LHSValue.getDecl() || !RHSValue.getDecl()) { bool Equal = !LHSValue.getDecl() && !RHSValue.getDecl(); - return Success(Equal ? CCR::Equal : CCR::Nonequal, E); + return Success(Equal ? CmpResult::Equal : CmpResult::Unequal, E); } // Otherwise if either is a pointer to a virtual member function, the @@ -11717,7 +11962,7 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, // they were dereferenced with a hypothetical object of the associated // class type. bool Equal = LHSValue == RHSValue; - return Success(Equal ? CCR::Equal : CCR::Nonequal, E); + return Success(Equal ? CmpResult::Equal : CmpResult::Unequal, E); } if (LHSTy->isNullPtrType()) { @@ -11726,7 +11971,7 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, // C++11 [expr.rel]p4, [expr.eq]p3: If two operands of type std::nullptr_t // are compared, the result is true of the operator is <=, >= or ==, and // false otherwise. - return Success(CCR::Equal, E); + return Success(CmpResult::Equal, E); } return DoAfter(); @@ -11736,14 +11981,29 @@ bool RecordExprEvaluator::VisitBinCmp(const BinaryOperator *E) { if (!CheckLiteralType(Info, E)) return false; - auto OnSuccess = [&](ComparisonCategoryResult ResKind, - const BinaryOperator *E) { + auto OnSuccess = [&](CmpResult CR, const BinaryOperator *E) { + ComparisonCategoryResult CCR; + switch (CR) { + case CmpResult::Unequal: + llvm_unreachable("should never produce Unequal for three-way comparison"); + case CmpResult::Less: + CCR = ComparisonCategoryResult::Less; + break; + case CmpResult::Equal: + CCR = ComparisonCategoryResult::Equal; + break; + case CmpResult::Greater: + CCR = ComparisonCategoryResult::Greater; + break; + case CmpResult::Unordered: + CCR = ComparisonCategoryResult::Unordered; + break; + } // Evaluation succeeded. Lookup the information for the comparison category // type and fetch the VarDecl for the result. const ComparisonCategoryInfo &CmpInfo = Info.Ctx.CompCategories.getInfoForType(E->getType()); - const VarDecl *VD = - CmpInfo.getValueInfo(CmpInfo.makeWeakResult(ResKind))->VD; + const VarDecl *VD = CmpInfo.getValueInfo(CmpInfo.makeWeakResult(CCR))->VD; // Check and evaluate the result as a constant expression. LValue LV; LV.set(VD); @@ -11771,14 +12031,14 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { "DataRecursiveIntBinOpEvaluator should have handled integral types"); if (E->isComparisonOp()) { - // Evaluate builtin binary comparisons by evaluating them as C++2a three-way + // Evaluate builtin binary comparisons by evaluating them as three-way // comparisons and then translating the result. - auto OnSuccess = [&](ComparisonCategoryResult ResKind, - const BinaryOperator *E) { - using CCR = ComparisonCategoryResult; - bool IsEqual = ResKind == CCR::Equal, - IsLess = ResKind == CCR::Less, - IsGreater = ResKind == CCR::Greater; + auto OnSuccess = [&](CmpResult CR, const BinaryOperator *E) { + assert((CR != CmpResult::Unequal || E->isEqualityOp()) && + "should only produce Unequal for equality comparisons"); + bool IsEqual = CR == CmpResult::Equal, + IsLess = CR == CmpResult::Less, + IsGreater = CR == CmpResult::Greater; auto Op = E->getOpcode(); switch (Op) { default: @@ -11786,10 +12046,14 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { case BO_EQ: case BO_NE: return Success(IsEqual == (Op == BO_EQ), E); - case BO_LT: return Success(IsLess, E); - case BO_GT: return Success(IsGreater, E); - case BO_LE: return Success(IsEqual || IsLess, E); - case BO_GE: return Success(IsEqual || IsGreater, E); + case BO_LT: + return Success(IsLess, E); + case BO_GT: + return Success(IsGreater, E); + case BO_LE: + return Success(IsEqual || IsLess, E); + case BO_GE: + return Success(IsEqual || IsGreater, E); } }; return EvaluateComparisonBinaryOperator(Info, E, OnSuccess, [&]() { @@ -13374,32 +13638,25 @@ static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, const LValue &This, /// EvaluateAsRValue - Try to evaluate this expression, performing an implicit /// lvalue-to-rvalue cast if it is an lvalue. static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) { - if (Info.EnableNewConstInterp) { - auto &InterpCtx = Info.Ctx.getInterpContext(); - switch (InterpCtx.evaluateAsRValue(Info, E, Result)) { - case interp::InterpResult::Success: - return true; - case interp::InterpResult::Fail: + if (Info.EnableNewConstInterp) { + if (!Info.Ctx.getInterpContext().evaluateAsRValue(Info, E, Result)) + return false; + } else { + if (E->getType().isNull()) return false; - case interp::InterpResult::Bail: - break; - } - } - - if (E->getType().isNull()) - return false; - - if (!CheckLiteralType(Info, E)) - return false; - if (!::Evaluate(Result, Info, E)) - return false; + if (!CheckLiteralType(Info, E)) + return false; - if (E->isGLValue()) { - LValue LV; - LV.setFrom(Info.Ctx, Result); - if (!handleLValueToRValueConversion(Info, E, E->getType(), LV, Result)) + if (!::Evaluate(Result, Info, E)) return false; + + if (E->isGLValue()) { + LValue LV; + LV.setFrom(Info.Ctx, Result); + if (!handleLValueToRValueConversion(Info, E, E->getType(), LV, Result)) + return false; + } } // Check this core constant expression is a constant expression. @@ -13611,46 +13868,36 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, if (Info.EnableNewConstInterp) { auto &InterpCtx = const_cast<ASTContext &>(Ctx).getInterpContext(); - switch (InterpCtx.evaluateAsInitializer(Info, VD, Value)) { - case interp::InterpResult::Fail: - // Bail out if an error was encountered. - return false; - case interp::InterpResult::Success: - // Evaluation succeeded and value was set. - return CheckConstantExpression(Info, DeclLoc, DeclTy, Value); - case interp::InterpResult::Bail: - // Evaluate the value again for the tree evaluator to use. - break; + if (!InterpCtx.evaluateAsInitializer(Info, VD, Value)) + return false; + } else { + LValue LVal; + LVal.set(VD); + + // C++11 [basic.start.init]p2: + // Variables with static storage duration or thread storage duration shall + // be zero-initialized before any other initialization takes place. + // This behavior is not present in C. + if (Ctx.getLangOpts().CPlusPlus && !VD->hasLocalStorage() && + !DeclTy->isReferenceType()) { + ImplicitValueInitExpr VIE(DeclTy); + if (!EvaluateInPlace(Value, Info, LVal, &VIE, + /*AllowNonLiteralTypes=*/true)) + return false; } - } - LValue LVal; - LVal.set(VD); - - // C++11 [basic.start.init]p2: - // Variables with static storage duration or thread storage duration shall be - // zero-initialized before any other initialization takes place. - // This behavior is not present in C. - if (Ctx.getLangOpts().CPlusPlus && !VD->hasLocalStorage() && - !DeclTy->isReferenceType()) { - ImplicitValueInitExpr VIE(DeclTy); - if (!EvaluateInPlace(Value, Info, LVal, &VIE, - /*AllowNonLiteralTypes=*/true)) + if (!EvaluateInPlace(Value, Info, LVal, this, + /*AllowNonLiteralTypes=*/true) || + EStatus.HasSideEffects) return false; - } - if (!EvaluateInPlace(Value, Info, LVal, this, - /*AllowNonLiteralTypes=*/true) || - EStatus.HasSideEffects) - return false; - - // At this point, any lifetime-extended temporaries are completely - // initialized. - Info.performLifetimeExtension(); - - if (!Info.discardCleanups()) - llvm_unreachable("Unhandled cleanup; missing full expression marker?"); + // At this point, any lifetime-extended temporaries are completely + // initialized. + Info.performLifetimeExtension(); + if (!Info.discardCleanups()) + llvm_unreachable("Unhandled cleanup; missing full expression marker?"); + } return CheckConstantExpression(Info, DeclLoc, DeclTy, Value) && CheckMemoryLeaks(Info); } @@ -14333,27 +14580,41 @@ bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx, assert(MD && "Don't provide `this` for non-methods."); assert(!MD->isStatic() && "Don't provide `this` for static methods."); #endif - if (EvaluateObjectArgument(Info, This, ThisVal)) + if (!This->isValueDependent() && + EvaluateObjectArgument(Info, This, ThisVal) && + !Info.EvalStatus.HasSideEffects) ThisPtr = &ThisVal; - if (Info.EvalStatus.HasSideEffects) - return false; + + // Ignore any side-effects from a failed evaluation. This is safe because + // they can't interfere with any other argument evaluation. + Info.EvalStatus.HasSideEffects = false; } ArgVector ArgValues(Args.size()); for (ArrayRef<const Expr*>::iterator I = Args.begin(), E = Args.end(); I != E; ++I) { if ((*I)->isValueDependent() || - !Evaluate(ArgValues[I - Args.begin()], Info, *I)) + !Evaluate(ArgValues[I - Args.begin()], Info, *I) || + Info.EvalStatus.HasSideEffects) // If evaluation fails, throw away the argument entirely. ArgValues[I - Args.begin()] = APValue(); - if (Info.EvalStatus.HasSideEffects) - return false; + + // Ignore any side-effects from a failed evaluation. This is safe because + // they can't interfere with any other argument evaluation. + Info.EvalStatus.HasSideEffects = false; } + // Parameter cleanups happen in the caller and are not part of this + // evaluation. + Info.discardCleanups(); + Info.EvalStatus.HasSideEffects = false; + // Build fake call to Callee. CallStackFrame Frame(Info, Callee->getLocation(), Callee, ThisPtr, ArgValues.data()); - return Evaluate(Value, Info, this) && Info.discardCleanups() && + // FIXME: Missing ExprWithCleanups in enable_if conditions? + FullExpressionRAII Scope(Info); + return Evaluate(Value, Info, this) && Scope.destroy() && !Info.EvalStatus.HasSideEffects; } @@ -14375,14 +14636,8 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, // The constexpr VM attempts to compile all methods to bytecode here. if (Info.EnableNewConstInterp) { - auto &InterpCtx = Info.Ctx.getInterpContext(); - switch (InterpCtx.isPotentialConstantExpr(Info, FD)) { - case interp::InterpResult::Success: - case interp::InterpResult::Fail: - return Diags.empty(); - case interp::InterpResult::Bail: - break; - } + Info.Ctx.getInterpContext().isPotentialConstantExpr(Info, FD); + return Diags.empty(); } const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); diff --git a/clang/lib/AST/ExternalASTMerger.cpp b/clang/lib/AST/ExternalASTMerger.cpp index f678c2dd3b59..88bbe90a4e90 100644 --- a/clang/lib/AST/ExternalASTMerger.cpp +++ b/clang/lib/AST/ExternalASTMerger.cpp @@ -510,9 +510,7 @@ bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC, Decl *LookupRes = C.first.get(); ASTImporter *Importer = C.second; auto NDOrErr = Importer->Import(LookupRes); - assert(NDOrErr); - (void)static_cast<bool>(NDOrErr); - NamedDecl *ND = cast_or_null<NamedDecl>(*NDOrErr); + NamedDecl *ND = cast<NamedDecl>(llvm::cantFail(std::move(NDOrErr))); assert(ND); // If we don't import specialization, they are not available via lookup // because the lookup result is imported TemplateDecl and it does not diff --git a/clang/lib/AST/ExternalASTSource.cpp b/clang/lib/AST/ExternalASTSource.cpp index 730102757440..837be5527fce 100644 --- a/clang/lib/AST/ExternalASTSource.cpp +++ b/clang/lib/AST/ExternalASTSource.cpp @@ -24,6 +24,8 @@ using namespace clang; +char ExternalASTSource::ID; + ExternalASTSource::~ExternalASTSource() = default; llvm::Optional<ExternalASTSource::ASTSourceDescriptor> diff --git a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp index c71301598bde..5b47489e65e0 100644 --- a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp @@ -14,13 +14,11 @@ #include "PrimType.h" #include "Program.h" #include "State.h" +#include "clang/Basic/LLVM.h" using namespace clang; using namespace clang::interp; -template <typename T> using Expected = llvm::Expected<T>; -template <typename T> using Optional = llvm::Optional<T>; - namespace clang { namespace interp { diff --git a/clang/lib/AST/Interp/Context.cpp b/clang/lib/AST/Interp/Context.cpp index 4f8f7b96e7c3..e7f9ba0f010a 100644 --- a/clang/lib/AST/Interp/Context.cpp +++ b/clang/lib/AST/Interp/Context.cpp @@ -21,44 +21,37 @@ using namespace clang; using namespace clang::interp; -Context::Context(ASTContext &Ctx) - : Ctx(Ctx), ForceInterp(getLangOpts().ForceNewConstInterp), - P(new Program(*this)) {} +Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new Program(*this)) {} Context::~Context() {} -InterpResult Context::isPotentialConstantExpr(State &Parent, - const FunctionDecl *FD) { +bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) { Function *Func = P->getFunction(FD); if (!Func) { if (auto R = ByteCodeStmtGen<ByteCodeEmitter>(*this, *P).compileFunc(FD)) { Func = *R; - } else if (ForceInterp) { + } else { handleAllErrors(R.takeError(), [&Parent](ByteCodeGenError &Err) { Parent.FFDiag(Err.getLoc(), diag::err_experimental_clang_interp_failed); }); - return InterpResult::Fail; - } else { - consumeError(R.takeError()); - return InterpResult::Bail; + return false; } } if (!Func->isConstexpr()) - return InterpResult::Fail; + return false; APValue Dummy; return Run(Parent, Func, Dummy); } -InterpResult Context::evaluateAsRValue(State &Parent, const Expr *E, - APValue &Result) { +bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) { ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result); return Check(Parent, C.interpretExpr(E)); } -InterpResult Context::evaluateAsInitializer(State &Parent, const VarDecl *VD, - APValue &Result) { +bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD, + APValue &Result) { ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result); return Check(Parent, C.interpretDecl(VD)); } @@ -116,33 +109,20 @@ unsigned Context::getCharBit() const { return Ctx.getTargetInfo().getCharWidth(); } -InterpResult Context::Run(State &Parent, Function *Func, APValue &Result) { - InterpResult Flag; - { - InterpState State(Parent, *P, Stk, *this); - State.Current = new InterpFrame(State, Func, nullptr, {}, {}); - if (Interpret(State, Result)) { - Flag = InterpResult::Success; - } else { - Flag = InterpResult::Fail; - } - } - - if (Flag != InterpResult::Success) - Stk.clear(); - return Flag; +bool Context::Run(State &Parent, Function *Func, APValue &Result) { + InterpState State(Parent, *P, Stk, *this); + State.Current = new InterpFrame(State, Func, nullptr, {}, {}); + if (Interpret(State, Result)) + return true; + Stk.clear(); + return false; } -InterpResult Context::Check(State &Parent, llvm::Expected<bool> &&R) { - if (R) { - return *R ? InterpResult::Success : InterpResult::Fail; - } else if (ForceInterp) { - handleAllErrors(R.takeError(), [&Parent](ByteCodeGenError &Err) { - Parent.FFDiag(Err.getLoc(), diag::err_experimental_clang_interp_failed); - }); - return InterpResult::Fail; - } else { - consumeError(R.takeError()); - return InterpResult::Bail; - } +bool Context::Check(State &Parent, llvm::Expected<bool> &&Flag) { + if (Flag) + return *Flag; + handleAllErrors(Flag.takeError(), [&Parent](ByteCodeGenError &Err) { + Parent.FFDiag(Err.getLoc(), diag::err_experimental_clang_interp_failed); + }); + return false; } diff --git a/clang/lib/AST/Interp/Context.h b/clang/lib/AST/Interp/Context.h index 96368b6e5f02..e4d831cbb991 100644 --- a/clang/lib/AST/Interp/Context.h +++ b/clang/lib/AST/Interp/Context.h @@ -34,16 +34,6 @@ class Program; class State; enum PrimType : unsigned; -/// Wrapper around interpreter termination results. -enum class InterpResult { - /// Interpreter successfully computed a value. - Success, - /// Interpreter encountered an error and quit. - Fail, - /// Interpreter encountered an unimplemented feature, AST fallback. - Bail, -}; - /// Holds all information required to evaluate constexpr code in a module. class Context { public: @@ -54,15 +44,13 @@ public: ~Context(); /// Checks if a function is a potential constant expression. - InterpResult isPotentialConstantExpr(State &Parent, - const FunctionDecl *FnDecl); + bool isPotentialConstantExpr(State &Parent, const FunctionDecl *FnDecl); /// Evaluates a toplevel expression as an rvalue. - InterpResult evaluateAsRValue(State &Parent, const Expr *E, APValue &Result); + bool evaluateAsRValue(State &Parent, const Expr *E, APValue &Result); /// Evaluates a toplevel initializer. - InterpResult evaluateAsInitializer(State &Parent, const VarDecl *VD, - APValue &Result); + bool evaluateAsInitializer(State &Parent, const VarDecl *VD, APValue &Result); /// Returns the AST context. ASTContext &getASTContext() const { return Ctx; } @@ -78,16 +66,14 @@ public: private: /// Runs a function. - InterpResult Run(State &Parent, Function *Func, APValue &Result); + bool Run(State &Parent, Function *Func, APValue &Result); /// Checks a result fromt the interpreter. - InterpResult Check(State &Parent, llvm::Expected<bool> &&R); + bool Check(State &Parent, llvm::Expected<bool> &&R); private: /// Current compilation context. ASTContext &Ctx; - /// Flag to indicate if the use of the interpreter is mandatory. - bool ForceInterp; /// Interpreter stack, shared across invocations. InterpStack Stk; /// Constexpr program. diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index 8934efa13b9c..c12caa639da7 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -196,11 +196,8 @@ inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) { const Pointer &RHS = S.Stk.pop<Pointer>(); const Pointer &LHS = S.Stk.pop<Pointer>(); - if (LHS.isZero() || RHS.isZero()) { - if (LHS.isZero() && RHS.isZero()) - S.Stk.push<BoolT>(BoolT::from(Fn(ComparisonCategoryResult::Equal))); - else - S.Stk.push<BoolT>(BoolT::from(Fn(ComparisonCategoryResult::Nonequal))); + if (LHS.isZero() && RHS.isZero()) { + S.Stk.push<BoolT>(BoolT::from(Fn(ComparisonCategoryResult::Equal))); return true; } diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index c55a90137578..0d567edac521 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -2301,6 +2301,16 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals, const DependentAddressSp case LangAS::cuda_device: ASString = "CUdevice"; break; case LangAS::cuda_constant: ASString = "CUconstant"; break; case LangAS::cuda_shared: ASString = "CUshared"; break; + // <ptrsize-addrspace> ::= [ "ptr32_sptr" | "ptr32_uptr" | "ptr64" ] + case LangAS::ptr32_sptr: + ASString = "ptr32_sptr"; + break; + case LangAS::ptr32_uptr: + ASString = "ptr32_uptr"; + break; + case LangAS::ptr64: + ASString = "ptr64"; + break; } } if (!ASString.empty()) @@ -4338,7 +4348,7 @@ recurse: } case Expr::MaterializeTemporaryExprClass: { - mangleExpression(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr()); + mangleExpression(cast<MaterializeTemporaryExpr>(E)->getSubExpr()); break; } diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp index f60d761c996c..c30b07137edc 100644 --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -202,14 +202,20 @@ void JSONNodeDumper::writeBareSourceLocation(SourceLocation Loc, PresumedLoc Presumed = SM.getPresumedLoc(Loc); unsigned ActualLine = IsSpelling ? SM.getSpellingLineNumber(Loc) : SM.getExpansionLineNumber(Loc); + StringRef ActualFile = SM.getBufferName(Loc); + if (Presumed.isValid()) { JOS.attribute("offset", SM.getDecomposedLoc(Loc).second); - if (LastLocFilename != Presumed.getFilename()) { - JOS.attribute("file", Presumed.getFilename()); + if (LastLocFilename != ActualFile) { + JOS.attribute("file", ActualFile); JOS.attribute("line", ActualLine); } else if (LastLocLine != ActualLine) JOS.attribute("line", ActualLine); + StringRef PresumedFile = Presumed.getFilename(); + if (PresumedFile != ActualFile && LastLocPresumedFilename != PresumedFile) + JOS.attribute("presumedFile", PresumedFile); + unsigned PresumedLine = Presumed.getLine(); if (ActualLine != PresumedLine && LastLocPresumedLine != PresumedLine) JOS.attribute("presumedLine", PresumedLine); @@ -217,7 +223,8 @@ void JSONNodeDumper::writeBareSourceLocation(SourceLocation Loc, JOS.attribute("col", Presumed.getColumn()); JOS.attribute("tokLen", Lexer::MeasureTokenLength(Loc, SM, Ctx.getLangOpts())); - LastLocFilename = Presumed.getFilename(); + LastLocFilename = ActualFile; + LastLocPresumedFilename = PresumedFile; LastLocPresumedLine = PresumedLine; LastLocLine = ActualLine; @@ -688,8 +695,12 @@ void JSONNodeDumper::VisitMemberPointerType(const MemberPointerType *MPT) { } void JSONNodeDumper::VisitNamedDecl(const NamedDecl *ND) { - if (ND && ND->getDeclName()) + if (ND && ND->getDeclName()) { JOS.attribute("name", ND->getNameAsString()); + std::string MangledName = ASTNameGen.getName(ND); + if (!MangledName.empty()) + JOS.attribute("mangledName", MangledName); + } } void JSONNodeDumper::VisitTypedefDecl(const TypedefDecl *TD) { @@ -874,12 +885,6 @@ void JSONNodeDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *LSD) { switch (LSD->getLanguage()) { case LinkageSpecDecl::lang_c: Lang = "C"; break; case LinkageSpecDecl::lang_cxx: Lang = "C++"; break; - case LinkageSpecDecl::lang_cxx_11: - Lang = "C++11"; - break; - case LinkageSpecDecl::lang_cxx_14: - Lang = "C++14"; - break; } JOS.attribute("language", Lang); attributeOnlyIfTrue("hasBraces", LSD->hasBraces()); @@ -1013,6 +1018,7 @@ void JSONNodeDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { attributeOnlyIfTrue("unsafe_unretained", Attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained); attributeOnlyIfTrue("class", Attrs & ObjCPropertyDecl::OBJC_PR_class); + attributeOnlyIfTrue("direct", Attrs & ObjCPropertyDecl::OBJC_PR_direct); attributeOnlyIfTrue("nullability", Attrs & ObjCPropertyDecl::OBJC_PR_nullability); attributeOnlyIfTrue("null_resettable", @@ -1512,6 +1518,9 @@ void JSONNodeDumper::visitInlineCommandComment( case comments::InlineCommandComment::RenderMonospaced: JOS.attribute("renderKind", "monospaced"); break; + case comments::InlineCommandComment::RenderAnchor: + JOS.attribute("renderKind", "anchor"); + break; } llvm::json::Array Args; diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp index 32d466cb5718..e106b31f59f0 100644 --- a/clang/lib/AST/Mangle.cpp +++ b/clang/lib/AST/Mangle.cpp @@ -63,9 +63,7 @@ static CCMangling getCallingConvMangling(const ASTContext &Context, const NamedDecl *ND) { const TargetInfo &TI = Context.getTargetInfo(); const llvm::Triple &Triple = TI.getTriple(); - if (!Triple.isOSWindows() || - !(Triple.getArch() == llvm::Triple::x86 || - Triple.getArch() == llvm::Triple::x86_64)) + if (!Triple.isOSWindows() || !Triple.isX86()) return CCM_Other; if (Context.getLangOpts().CPlusPlus && !isExternC(ND) && diff --git a/clang/lib/AST/MicrosoftCXXABI.cpp b/clang/lib/AST/MicrosoftCXXABI.cpp index 074abba3d458..f9f9fe985b6f 100644 --- a/clang/lib/AST/MicrosoftCXXABI.cpp +++ b/clang/lib/AST/MicrosoftCXXABI.cpp @@ -14,6 +14,7 @@ #include "CXXABI.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" +#include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/MangleNumberingContext.h" #include "clang/AST/RecordLayout.h" @@ -154,27 +155,32 @@ static bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) { return false; } -MSInheritanceAttr::Spelling CXXRecordDecl::calculateInheritanceModel() const { +MSInheritanceModel CXXRecordDecl::calculateInheritanceModel() const { if (!hasDefinition() || isParsingBaseSpecifiers()) - return MSInheritanceAttr::Keyword_unspecified_inheritance; + return MSInheritanceModel::Unspecified; if (getNumVBases() > 0) - return MSInheritanceAttr::Keyword_virtual_inheritance; + return MSInheritanceModel::Virtual; if (usesMultipleInheritanceModel(this)) - return MSInheritanceAttr::Keyword_multiple_inheritance; - return MSInheritanceAttr::Keyword_single_inheritance; + return MSInheritanceModel::Multiple; + return MSInheritanceModel::Single; } -MSInheritanceAttr::Spelling -CXXRecordDecl::getMSInheritanceModel() const { +MSInheritanceModel CXXRecordDecl::getMSInheritanceModel() const { MSInheritanceAttr *IA = getAttr<MSInheritanceAttr>(); assert(IA && "Expected MSInheritanceAttr on the CXXRecordDecl!"); - return IA->getSemanticSpelling(); + return IA->getInheritanceModel(); } -MSVtorDispAttr::Mode CXXRecordDecl::getMSVtorDispMode() const { +bool CXXRecordDecl::nullFieldOffsetIsZero() const { + return !inheritanceModelHasOnlyOneField(/*IsMemberFunction=*/false, + getMSInheritanceModel()) || + (hasDefinition() && isPolymorphic()); +} + +MSVtorDispMode CXXRecordDecl::getMSVtorDispMode() const { if (MSVtorDispAttr *VDA = getAttr<MSVtorDispAttr>()) return VDA->getVtorDispMode(); - return MSVtorDispAttr::Mode(getASTContext().getLangOpts().VtorDispMode); + return getASTContext().getLangOpts().getVtorDispMode(); } // Returns the number of pointer and integer slots used to represent a member @@ -209,19 +215,19 @@ MSVtorDispAttr::Mode CXXRecordDecl::getMSVtorDispMode() const { static std::pair<unsigned, unsigned> getMSMemberPointerSlots(const MemberPointerType *MPT) { const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); - MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); + MSInheritanceModel Inheritance = RD->getMSInheritanceModel(); unsigned Ptrs = 0; unsigned Ints = 0; if (MPT->isMemberFunctionPointer()) Ptrs = 1; else Ints = 1; - if (MSInheritanceAttr::hasNVOffsetField(MPT->isMemberFunctionPointer(), + if (inheritanceModelHasNVOffsetField(MPT->isMemberFunctionPointer(), Inheritance)) Ints++; - if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance)) + if (inheritanceModelHasVBPtrOffsetField(Inheritance)) Ints++; - if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance)) + if (inheritanceModelHasVBTableOffsetField(Inheritance)) Ints++; return std::make_pair(Ptrs, Ints); } diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index f871a1b99900..a286c5335584 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -279,8 +279,6 @@ class MicrosoftCXXNameMangler { ASTContext &getASTContext() const { return Context.getASTContext(); } - // FIXME: If we add support for __ptr32/64 qualifiers, then we should push - // this check into mangleQualifiers(). const bool PointersAre64Bit; public: @@ -335,6 +333,13 @@ private: return ND == Structor || getStructor(ND) == Structor; } + bool is64BitPointer(Qualifiers Quals) const { + LangAS AddrSpace = Quals.getAddressSpace(); + return AddrSpace == LangAS::ptr64 || + (PointersAre64Bit && !(AddrSpace == LangAS::ptr32_sptr || + AddrSpace == LangAS::ptr32_uptr)); + } + void mangleUnqualifiedName(const NamedDecl *ND) { mangleUnqualifiedName(ND, ND->getDeclName()); } @@ -592,7 +597,7 @@ void MicrosoftCXXNameMangler::mangleMemberDataPointer(const CXXRecordDecl *RD, int64_t FieldOffset; int64_t VBTableOffset; - MSInheritanceAttr::Spelling IM = RD->getMSInheritanceModel(); + MSInheritanceModel IM = RD->getMSInheritanceModel(); if (VD) { FieldOffset = getASTContext().getFieldOffset(VD); assert(FieldOffset % getASTContext().getCharWidth() == 0 && @@ -601,7 +606,7 @@ void MicrosoftCXXNameMangler::mangleMemberDataPointer(const CXXRecordDecl *RD, VBTableOffset = 0; - if (IM == MSInheritanceAttr::Keyword_virtual_inheritance) + if (IM == MSInheritanceModel::Virtual) FieldOffset -= getASTContext().getOffsetOfBaseWithVBPtr(RD).getQuantity(); } else { FieldOffset = RD->nullFieldOffsetIsZero() ? 0 : -1; @@ -611,12 +616,10 @@ void MicrosoftCXXNameMangler::mangleMemberDataPointer(const CXXRecordDecl *RD, char Code = '\0'; switch (IM) { - case MSInheritanceAttr::Keyword_single_inheritance: Code = '0'; break; - case MSInheritanceAttr::Keyword_multiple_inheritance: Code = '0'; break; - case MSInheritanceAttr::Keyword_virtual_inheritance: Code = 'F'; break; - case MSInheritanceAttr::Keyword_unspecified_inheritance: Code = 'G'; break; - case MSInheritanceAttr::SpellingNotCalculated: - llvm_unreachable("not reachable"); + case MSInheritanceModel::Single: Code = '0'; break; + case MSInheritanceModel::Multiple: Code = '0'; break; + case MSInheritanceModel::Virtual: Code = 'F'; break; + case MSInheritanceModel::Unspecified: Code = 'G'; break; } Out << '$' << Code; @@ -626,9 +629,9 @@ void MicrosoftCXXNameMangler::mangleMemberDataPointer(const CXXRecordDecl *RD, // The C++ standard doesn't allow base-to-derived member pointer conversions // in template parameter contexts, so the vbptr offset of data member pointers // is always zero. - if (MSInheritanceAttr::hasVBPtrOffsetField(IM)) + if (inheritanceModelHasVBPtrOffsetField(IM)) mangleNumber(0); - if (MSInheritanceAttr::hasVBTableOffsetField(IM)) + if (inheritanceModelHasVBTableOffsetField(IM)) mangleNumber(VBTableOffset); } @@ -640,16 +643,14 @@ MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD, // ::= $I? <name> <number> <number> // ::= $J? <name> <number> <number> <number> - MSInheritanceAttr::Spelling IM = RD->getMSInheritanceModel(); + MSInheritanceModel IM = RD->getMSInheritanceModel(); char Code = '\0'; switch (IM) { - case MSInheritanceAttr::Keyword_single_inheritance: Code = '1'; break; - case MSInheritanceAttr::Keyword_multiple_inheritance: Code = 'H'; break; - case MSInheritanceAttr::Keyword_virtual_inheritance: Code = 'I'; break; - case MSInheritanceAttr::Keyword_unspecified_inheritance: Code = 'J'; break; - case MSInheritanceAttr::SpellingNotCalculated: - llvm_unreachable("not reachable"); + case MSInheritanceModel::Single: Code = '1'; break; + case MSInheritanceModel::Multiple: Code = 'H'; break; + case MSInheritanceModel::Virtual: Code = 'I'; break; + case MSInheritanceModel::Unspecified: Code = 'J'; break; } // If non-virtual, mangle the name. If virtual, mangle as a virtual memptr @@ -676,25 +677,24 @@ MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD, mangleFunctionEncoding(MD, /*ShouldMangle=*/true); } - if (VBTableOffset == 0 && - IM == MSInheritanceAttr::Keyword_virtual_inheritance) + if (VBTableOffset == 0 && IM == MSInheritanceModel::Virtual) NVOffset -= getASTContext().getOffsetOfBaseWithVBPtr(RD).getQuantity(); } else { // Null single inheritance member functions are encoded as a simple nullptr. - if (IM == MSInheritanceAttr::Keyword_single_inheritance) { + if (IM == MSInheritanceModel::Single) { Out << "$0A@"; return; } - if (IM == MSInheritanceAttr::Keyword_unspecified_inheritance) + if (IM == MSInheritanceModel::Unspecified) VBTableOffset = -1; Out << '$' << Code; } - if (MSInheritanceAttr::hasNVOffsetField(/*IsMemberFunction=*/true, IM)) + if (inheritanceModelHasNVOffsetField(/*IsMemberFunction=*/true, IM)) mangleNumber(static_cast<uint32_t>(NVOffset)); - if (MSInheritanceAttr::hasVBPtrOffsetField(IM)) + if (inheritanceModelHasVBPtrOffsetField(IM)) mangleNumber(VBPtrOffset); - if (MSInheritanceAttr::hasVBTableOffsetField(IM)) + if (inheritanceModelHasVBTableOffsetField(IM)) mangleNumber(VBTableOffset); } @@ -710,7 +710,7 @@ void MicrosoftCXXNameMangler::mangleVirtualMemPtrThunk( Out << "$B"; mangleNumber(OffsetInVFTable); Out << 'A'; - mangleCallingConvention(MD->getType()->getAs<FunctionProtoType>()); + mangleCallingConvention(MD->getType()->castAs<FunctionProtoType>()); } void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) { @@ -1708,8 +1708,10 @@ MicrosoftCXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) { void MicrosoftCXXNameMangler::manglePointerExtQualifiers(Qualifiers Quals, QualType PointeeType) { - if (PointersAre64Bit && - (PointeeType.isNull() || !PointeeType->isFunctionType())) + // Check if this is a default 64-bit pointer or has __ptr64 qualifier. + bool is64Bit = PointeeType.isNull() ? PointersAre64Bit : + is64BitPointer(PointeeType.getQualifiers()); + if (is64Bit && (PointeeType.isNull() || !PointeeType->isFunctionType())) Out << 'E'; if (Quals.hasRestrict()) @@ -1869,6 +1871,10 @@ void MicrosoftCXXNameMangler::mangleAddressSpaceType(QualType T, case LangAS::cuda_shared: Extra.mangleSourceName("_ASCUshared"); break; + case LangAS::ptr32_sptr: + case LangAS::ptr32_uptr: + case LangAS::ptr64: + llvm_unreachable("don't mangle ptr address spaces with _AS"); } } @@ -2602,10 +2608,13 @@ void MicrosoftCXXNameMangler::mangleType(const PointerType *T, Qualifiers Quals, manglePointerCVQualifiers(Quals); manglePointerExtQualifiers(Quals, PointeeType); - if (PointeeType.getQualifiers().hasAddressSpace()) - mangleAddressSpaceType(PointeeType, PointeeType.getQualifiers(), Range); - else + // For pointer size address spaces, go down the same type mangling path as + // non address space types. + LangAS AddrSpace = PointeeType.getQualifiers().getAddressSpace(); + if (isPtrSizeAddressSpace(AddrSpace) || AddrSpace == LangAS::Default) mangleType(PointeeType, Range); + else + mangleAddressSpaceType(PointeeType, PointeeType.getQualifiers(), Range); } void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T, @@ -2692,9 +2701,7 @@ void MicrosoftCXXNameMangler::mangleType(const VectorType *T, Qualifiers Quals, // doesn't match the Intel types uses a custom mangling below. size_t OutSizeBefore = Out.tell(); if (!isa<ExtVectorType>(T)) { - llvm::Triple::ArchType AT = - getASTContext().getTargetInfo().getTriple().getArch(); - if (AT == llvm::Triple::x86 || AT == llvm::Triple::x86_64) { + if (getASTContext().getTargetInfo().getTriple().isX86()) { if (Width == 64 && ET->getKind() == BuiltinType::LongLong) { mangleArtificialTagType(TTK_Union, "__m64"); } else if (Width >= 128) { diff --git a/clang/lib/AST/NestedNameSpecifier.cpp b/clang/lib/AST/NestedNameSpecifier.cpp index 09d85102585b..137953fa8203 100644 --- a/clang/lib/AST/NestedNameSpecifier.cpp +++ b/clang/lib/AST/NestedNameSpecifier.cpp @@ -472,7 +472,7 @@ TypeLoc NestedNameSpecifierLoc::getTypeLoc() const { } static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, - unsigned &BufferCapacity) { + unsigned &BufferCapacity) { if (Start == End) return; @@ -489,9 +489,9 @@ static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, Buffer = NewBuffer; BufferCapacity = NewCapacity; } - + assert(Buffer && Start && End && End > Start && "Illegal memory buffer copy"); memcpy(Buffer + BufferSize, Start, End - Start); - BufferSize += End-Start; + BufferSize += End - Start; } /// Save a source location to the given buffer. diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 3b89c630b451..27fdca1c4b9c 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -380,6 +380,11 @@ public: } Hash.AddBoolean(D->isParameterPack()); + const TypeConstraint *TC = D->getTypeConstraint(); + Hash.AddBoolean(TC != nullptr); + if (TC) + AddStmt(TC->getImmediatelyDeclaredConstraint()); + Inherited::VisitTemplateTypeParmDecl(D); } diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index fe1334469d48..5ef82648c89d 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -15,6 +15,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclOpenMP.h" #include "clang/Basic/LLVM.h" +#include "clang/Basic/OpenMPKinds.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" @@ -135,6 +136,7 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { case OMPC_atomic_default_mem_order: case OMPC_device_type: case OMPC_match: + case OMPC_nontemporal: break; } @@ -213,6 +215,7 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) case OMPC_atomic_default_mem_order: case OMPC_device_type: case OMPC_match: + case OMPC_nontemporal: break; } @@ -402,11 +405,12 @@ void OMPLastprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) { OMPLastprivateClause *OMPLastprivateClause::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs, - ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps, Stmt *PreInit, - Expr *PostUpdate) { + ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps, + OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, + SourceLocation ColonLoc, Stmt *PreInit, Expr *PostUpdate) { void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size())); - OMPLastprivateClause *Clause = - new (Mem) OMPLastprivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); + OMPLastprivateClause *Clause = new (Mem) OMPLastprivateClause( + StartLoc, LParenLoc, EndLoc, LPKind, LPKindLoc, ColonLoc, VL.size()); Clause->setVarRefs(VL); Clause->setSourceExprs(SrcExprs); Clause->setDestinationExprs(DstExprs); @@ -1155,13 +1159,38 @@ OMPIsDevicePtrClause::CreateEmpty(const ASTContext &C, return new (Mem) OMPIsDevicePtrClause(Sizes); } +OMPNontemporalClause *OMPNontemporalClause::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, + ArrayRef<Expr *> VL) { + // Allocate space for nontemporal variables + private references. + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * VL.size())); + auto *Clause = + new (Mem) OMPNontemporalClause(StartLoc, LParenLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + return Clause; +} + +OMPNontemporalClause *OMPNontemporalClause::CreateEmpty(const ASTContext &C, + unsigned N) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * N)); + return new (Mem) OMPNontemporalClause(N); +} + +void OMPNontemporalClause::setPrivateRefs(ArrayRef<Expr *> VL) { + assert(VL.size() == varlist_size() && "Number of private references is not " + "the same as the preallocated buffer"); + std::copy(VL.begin(), VL.end(), varlist_end()); +} + //===----------------------------------------------------------------------===// // OpenMP clauses printing methods //===----------------------------------------------------------------------===// void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) { OS << "if("; - if (Node->getNameModifier() != OMPD_unknown) + if (Node->getNameModifier() != llvm::omp::OMPD_unknown) OS << getOpenMPDirectiveName(Node->getNameModifier()) << ": "; Node->getCondition()->printPretty(OS, nullptr, Policy, 0); OS << ")"; @@ -1211,7 +1240,8 @@ void OMPClausePrinter::VisitOMPDefaultClause(OMPDefaultClause *Node) { void OMPClausePrinter::VisitOMPProcBindClause(OMPProcBindClause *Node) { OS << "proc_bind(" - << getOpenMPSimpleClauseTypeName(OMPC_proc_bind, Node->getProcBindKind()) + << getOpenMPSimpleClauseTypeName(OMPC_proc_bind, + unsigned(Node->getProcBindKind())) << ")"; } @@ -1401,7 +1431,13 @@ void OMPClausePrinter::VisitOMPFirstprivateClause(OMPFirstprivateClause *Node) { void OMPClausePrinter::VisitOMPLastprivateClause(OMPLastprivateClause *Node) { if (!Node->varlist_empty()) { OS << "lastprivate"; - VisitOMPClauseList(Node, '('); + OpenMPLastprivateModifier LPKind = Node->getKind(); + if (LPKind != OMPC_LASTPRIVATE_unknown) { + OS << "(" + << getOpenMPSimpleClauseTypeName(OMPC_lastprivate, Node->getKind()) + << ":"; + } + VisitOMPClauseList(Node, LPKind == OMPC_LASTPRIVATE_unknown ? '(' : ' '); OS << ")"; } } @@ -1648,3 +1684,10 @@ void OMPClausePrinter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *Node) { } } +void OMPClausePrinter::VisitOMPNontemporalClause(OMPNontemporalClause *Node) { + if (!Node->varlist_empty()) { + OS << "nontemporal"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp index f28f00171cce..73a33a208233 100644 --- a/clang/lib/AST/QualTypeNames.cpp +++ b/clang/lib/AST/QualTypeNames.cpp @@ -192,7 +192,7 @@ static NestedNameSpecifier *createOuterNNS(const ASTContext &Ctx, const Decl *D, // Ignore inline namespace; NS = dyn_cast<NamespaceDecl>(NS->getDeclContext()); } - if (NS->getDeclName()) { + if (NS && NS->getDeclName()) { return createNestedNameSpecifier(Ctx, NS, WithGlobalNsPrefix); } return nullptr; // no starting '::', no anonymous diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 2a3419a0cec3..9a21732b63e3 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2956,7 +2956,7 @@ void MicrosoftRecordLayoutBuilder::computeVtorDispSet( const CXXRecordDecl *RD) const { // /vd2 or #pragma vtordisp(2): Always use vtordisps for virtual bases with // vftables. - if (RD->getMSVtorDispMode() == MSVtorDispAttr::ForVFTable) { + if (RD->getMSVtorDispMode() == MSVtorDispMode::ForVFTable) { for (const CXXBaseSpecifier &Base : RD->vbases()) { const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl); @@ -2979,12 +2979,12 @@ void MicrosoftRecordLayoutBuilder::computeVtorDispSet( // * A user declared constructor or destructor aren't declared. // * #pragma vtordisp(0) or the /vd0 flag are in use. if ((!RD->hasUserDeclaredConstructor() && !RD->hasUserDeclaredDestructor()) || - RD->getMSVtorDispMode() == MSVtorDispAttr::Never) + RD->getMSVtorDispMode() == MSVtorDispMode::Never) return; // /vd1 or #pragma vtordisp(1): Try to guess based on whether we think it's // possible for a partially constructed object with virtual base overrides to // escape a non-trivial constructor. - assert(RD->getMSVtorDispMode() == MSVtorDispAttr::ForVBaseOverride); + assert(RD->getMSVtorDispMode() == MSVtorDispMode::ForVBaseOverride); // Compute a set of base classes which define methods we override. A virtual // base in this set will require a vtordisp. A virtual base that transitively // contains one of these bases as a non-virtual base will also require a diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 80a1451ac789..b6e4d8aff21e 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -908,6 +908,12 @@ bool IfStmt::isObjCAvailabilityCheck() const { return isa<ObjCAvailabilityCheckExpr>(getCond()); } +Optional<const Stmt*> IfStmt::getNondiscardedCase(const ASTContext &Ctx) const { + if (!isConstexpr() || getCond()->isValueDependent()) + return None; + return !getCond()->EvaluateKnownConstInt(Ctx) ? getElse() : getThen(); +} + ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP, SourceLocation RP) diff --git a/clang/lib/AST/StmtOpenMP.cpp b/clang/lib/AST/StmtOpenMP.cpp index da1364ebffc4..da6d308ad15b 100644 --- a/clang/lib/AST/StmtOpenMP.cpp +++ b/clang/lib/AST/StmtOpenMP.cpp @@ -15,6 +15,7 @@ #include "clang/AST/ASTContext.h" using namespace clang; +using namespace llvm::omp; void OMPExecutableDirective::setClauses(ArrayRef<OMPClause *> Clauses) { assert(Clauses.size() == getNumClauses() && @@ -41,6 +42,74 @@ const Stmt *OMPExecutableDirective::getStructuredBlock() const { return getInnermostCapturedStmt()->getCapturedStmt(); } +Stmt *OMPLoopDirective::tryToFindNextInnerLoop(Stmt *CurStmt, + bool TryImperfectlyNestedLoops) { + Stmt *OrigStmt = CurStmt; + CurStmt = CurStmt->IgnoreContainers(); + // Additional work for imperfectly nested loops, introduced in OpenMP 5.0. + if (TryImperfectlyNestedLoops) { + if (auto *CS = dyn_cast<CompoundStmt>(CurStmt)) { + CurStmt = nullptr; + SmallVector<CompoundStmt *, 4> Statements(1, CS); + SmallVector<CompoundStmt *, 4> NextStatements; + while (!Statements.empty()) { + CS = Statements.pop_back_val(); + if (!CS) + continue; + for (Stmt *S : CS->body()) { + if (!S) + continue; + if (isa<ForStmt>(S) || isa<CXXForRangeStmt>(S)) { + // Only single loop construct is allowed. + if (CurStmt) { + CurStmt = OrigStmt; + break; + } + CurStmt = S; + continue; + } + S = S->IgnoreContainers(); + if (auto *InnerCS = dyn_cast_or_null<CompoundStmt>(S)) + NextStatements.push_back(InnerCS); + } + if (Statements.empty()) { + // Found single inner loop or multiple loops - exit. + if (CurStmt) + break; + Statements.swap(NextStatements); + } + } + if (!CurStmt) + CurStmt = OrigStmt; + } + } + return CurStmt; +} + +Stmt *OMPLoopDirective::getBody() { + // This relies on the loop form is already checked by Sema. + Stmt *Body = + getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers(); + if (auto *For = dyn_cast<ForStmt>(Body)) { + Body = For->getBody(); + } else { + assert(isa<CXXForRangeStmt>(Body) && + "Expected canonical for loop or range-based for loop."); + Body = cast<CXXForRangeStmt>(Body)->getBody(); + } + for (unsigned Cnt = 1; Cnt < CollapsedNum; ++Cnt) { + Body = tryToFindNextInnerLoop(Body, /*TryImperfectlyNestedLoops=*/true); + if (auto *For = dyn_cast<ForStmt>(Body)) { + Body = For->getBody(); + } else { + assert(isa<CXXForRangeStmt>(Body) && + "Expected canonical for loop or range-based for loop."); + Body = cast<CXXForRangeStmt>(Body)->getBody(); + } + } + return Body; +} + void OMPLoopDirective::setCounters(ArrayRef<Expr *> A) { assert(A.size() == getCollapsedNumber() && "Number of loop counters is not the same as the collapsed number"); @@ -482,6 +551,30 @@ OMPParallelForSimdDirective::CreateEmpty(const ASTContext &C, return new (Mem) OMPParallelForSimdDirective(CollapsedNum, NumClauses); } +OMPParallelMasterDirective *OMPParallelMasterDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { + unsigned Size = + llvm::alignTo(sizeof(OMPParallelMasterDirective), alignof(OMPClause *)); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + auto *Dir = + new (Mem) OMPParallelMasterDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPParallelMasterDirective *OMPParallelMasterDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + EmptyShell) { + unsigned Size = + llvm::alignTo(sizeof(OMPParallelMasterDirective), alignof(OMPClause *)); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + return new (Mem) OMPParallelMasterDirective(NumClauses); +} + OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) { @@ -1182,6 +1275,63 @@ OMPParallelMasterTaskLoopDirective::CreateEmpty(const ASTContext &C, return new (Mem) OMPParallelMasterTaskLoopDirective(CollapsedNum, NumClauses); } +OMPParallelMasterTaskLoopSimdDirective * +OMPParallelMasterTaskLoopSimdDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + unsigned Size = llvm::alignTo(sizeof(OMPParallelMasterTaskLoopSimdDirective), + alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_parallel_master_taskloop_simd)); + auto *Dir = new (Mem) OMPParallelMasterTaskLoopSimdDirective( + StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setDependentCounters(Exprs.DependentCounters); + Dir->setDependentInits(Exprs.DependentInits); + Dir->setFinalsConditions(Exprs.FinalsConditions); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPParallelMasterTaskLoopSimdDirective * +OMPParallelMasterTaskLoopSimdDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + unsigned Size = llvm::alignTo(sizeof(OMPParallelMasterTaskLoopSimdDirective), + alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_parallel_master_taskloop_simd)); + return new (Mem) + OMPParallelMasterTaskLoopSimdDirective(CollapsedNum, NumClauses); +} + OMPDistributeDirective *OMPDistributeDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 7759ff6c1389..c14bb886bb11 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -697,7 +697,7 @@ void StmtPrinter::VisitOMPCriticalDirective(OMPCriticalDirective *Node) { Indent() << "#pragma omp critical"; if (Node->getDirectiveName().getName()) { OS << " ("; - Node->getDirectiveName().printName(OS); + Node->getDirectiveName().printName(OS, Policy); OS << ")"; } PrintOMPExecutableDirective(Node); @@ -714,6 +714,12 @@ void StmtPrinter::VisitOMPParallelForSimdDirective( PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPParallelMasterDirective( + OMPParallelMasterDirective *Node) { + Indent() << "#pragma omp parallel master"; + PrintOMPExecutableDirective(Node); +} + void StmtPrinter::VisitOMPParallelSectionsDirective( OMPParallelSectionsDirective *Node) { Indent() << "#pragma omp parallel sections"; @@ -841,6 +847,12 @@ void StmtPrinter::VisitOMPParallelMasterTaskLoopDirective( PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPParallelMasterTaskLoopSimdDirective( + OMPParallelMasterTaskLoopSimdDirective *Node) { + Indent() << "#pragma omp parallel master taskloop simd"; + PrintOMPExecutableDirective(Node); +} + void StmtPrinter::VisitOMPDistributeDirective(OMPDistributeDirective *Node) { Indent() << "#pragma omp distribute"; PrintOMPExecutableDirective(Node); @@ -1298,7 +1310,7 @@ void StmtPrinter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node){ void StmtPrinter::VisitGenericSelectionExpr(GenericSelectionExpr *Node) { OS << "_Generic("; PrintExpr(Node->getControllingExpr()); - for (const GenericSelectionExpr::Association &Assoc : Node->associations()) { + for (const GenericSelectionExpr::Association Assoc : Node->associations()) { OS << ", "; QualType T = Assoc.getType(); if (T.isNull()) @@ -2229,7 +2241,7 @@ void StmtPrinter::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) { } void StmtPrinter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *Node){ - PrintExpr(Node->GetTemporaryExpr()); + PrintExpr(Node->getSubExpr()); } void StmtPrinter::VisitCXXFoldExpr(CXXFoldExpr *E) { diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index d1e856538932..2aa5106e90fa 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -769,7 +769,13 @@ void OMPClauseProfiler::VisitOMPIsDevicePtrClause( const OMPIsDevicePtrClause *C) { VisitOMPClauseList(C); } +void OMPClauseProfiler::VisitOMPNontemporalClause( + const OMPNontemporalClause *C) { + VisitOMPClauseList(C); + for (auto *E : C->private_refs()) + Profiler->VisitStmt(E); } +} // namespace void StmtProfiler::VisitOMPExecutableDirective(const OMPExecutableDirective *S) { @@ -833,6 +839,11 @@ void StmtProfiler::VisitOMPParallelForSimdDirective( VisitOMPLoopDirective(S); } +void StmtProfiler::VisitOMPParallelMasterDirective( + const OMPParallelMasterDirective *S) { + VisitOMPExecutableDirective(S); +} + void StmtProfiler::VisitOMPParallelSectionsDirective( const OMPParallelSectionsDirective *S) { VisitOMPExecutableDirective(S); @@ -937,6 +948,11 @@ void StmtProfiler::VisitOMPParallelMasterTaskLoopDirective( VisitOMPLoopDirective(S); } +void StmtProfiler::VisitOMPParallelMasterTaskLoopSimdDirective( + const OMPParallelMasterTaskLoopSimdDirective *S) { + VisitOMPLoopDirective(S); +} + void StmtProfiler::VisitOMPDistributeDirective( const OMPDistributeDirective *S) { VisitOMPLoopDirective(S); @@ -1291,7 +1307,7 @@ void StmtProfiler::VisitBlockExpr(const BlockExpr *S) { void StmtProfiler::VisitGenericSelectionExpr(const GenericSelectionExpr *S) { VisitExpr(S); - for (const GenericSelectionExpr::ConstAssociation &Assoc : + for (const GenericSelectionExpr::ConstAssociation Assoc : S->associations()) { QualType T = Assoc.getType(); if (T.isNull()) diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 63a6510324f7..965ad17fcfa5 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -489,6 +489,9 @@ void TextNodeDumper::visitInlineCommandComment( case comments::InlineCommandComment::RenderEmphasized: OS << " RenderEmphasized"; break; + case comments::InlineCommandComment::RenderAnchor: + OS << " RenderAnchor"; + break; } for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) @@ -1338,6 +1341,17 @@ void TextNodeDumper::VisitFunctionDecl(const FunctionDecl *D) { OS << " <<<NULL params x " << D->getNumParams() << ">>>"; } +void TextNodeDumper::VisitLifetimeExtendedTemporaryDecl( + const LifetimeExtendedTemporaryDecl *D) { + OS << " extended by "; + dumpBareDeclRef(D->getExtendingDecl()); + OS << " mangling "; + { + ColorScope Color(OS, ShowColors, ValueColor); + OS << D->getManglingNumber(); + } +} + void TextNodeDumper::VisitFieldDecl(const FieldDecl *D) { dumpName(D); dumpType(D->getType()); @@ -1680,7 +1694,16 @@ void TextNodeDumper::VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) { } void TextNodeDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { - if (D->wasDeclaredWithTypename()) + if (const auto *TC = D->getTypeConstraint()) { + OS << " "; + dumpBareDeclRef(TC->getNamedConcept()); + if (TC->getNamedConcept() != TC->getFoundDecl()) { + OS << " ("; + dumpBareDeclRef(TC->getFoundDecl()); + OS << ")"; + } + Visit(TC->getImmediatelyDeclaredConstraint()); + } else if (D->wasDeclaredWithTypename()) OS << " typename"; else OS << " class"; @@ -1769,12 +1792,6 @@ void TextNodeDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) { case LinkageSpecDecl::lang_cxx: OS << " C++"; break; - case LinkageSpecDecl::lang_cxx_11: - OS << " C++11"; - break; - case LinkageSpecDecl::lang_cxx_14: - OS << " C++14"; - break; } } @@ -1921,6 +1938,8 @@ void TextNodeDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { OS << " unsafe_unretained"; if (Attrs & ObjCPropertyDecl::OBJC_PR_class) OS << " class"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_direct) + OS << " direct"; if (Attrs & ObjCPropertyDecl::OBJC_PR_getter) dumpDeclRef(D->getGetterMethodDecl(), "getter"); if (Attrs & ObjCPropertyDecl::OBJC_PR_setter) diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 4d54ea1061ed..c5ad711d872e 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -663,10 +663,6 @@ ObjCTypeParamType::ObjCTypeParamType(const ObjCTypeParamDecl *D, initialize(protocols); } -QualType ObjCTypeParamType::desugar() const { - return getDecl()->getUnderlyingType(); -} - ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base, ArrayRef<QualType> typeArgs, ArrayRef<ObjCProtocolDecl *> protocols, @@ -1860,13 +1856,12 @@ bool Type::isIntegralOrUnscopedEnumerationType() const { if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && BT->getKind() <= BuiltinType::Int128; + return isUnscopedEnumerationType(); +} - // Check for a complete enum type; incomplete enum types are not properly an - // enumeration type in the sense required here. - // C++0x: However, if the underlying type of the enum is fixed, it is - // considered complete. +bool Type::isUnscopedEnumerationType() const { if (const auto *ET = dyn_cast<EnumType>(CanonicalType)) - return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped(); + return !ET->getDecl()->isScoped(); return false; } @@ -3069,6 +3064,12 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, } else { FunctionTypeBits.HasExtQuals = 0; } + + // Fill in the Ellipsis location info if present. + if (epi.Variadic) { + auto &EllipsisLoc = *getTrailingObjects<SourceLocation>(); + EllipsisLoc = epi.EllipsisLoc; + } } bool FunctionProtoType::hasDependentExceptionSpec() const { diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp index e4788f32b265..6e67ca8e0af7 100644 --- a/clang/lib/AST/TypeLoc.cpp +++ b/clang/lib/AST/TypeLoc.cpp @@ -12,6 +12,7 @@ #include "clang/AST/TypeLoc.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" #include "clang/AST/Expr.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateBase.h" @@ -293,6 +294,12 @@ bool TypeSpecTypeLoc::isKind(const TypeLoc &TL) { return TSTChecker().Visit(TL); } +bool TagTypeLoc::isDefinition() const { + TagDecl *D = getDecl(); + return D->isCompleteDefinition() && + (D->getIdentifier() == nullptr || D->getLocation() == getNameLoc()); +} + // Reimplemented to account for GNU/C++ extension // typeof unary-expression // where there are no parentheses. @@ -467,6 +474,19 @@ void ObjCObjectTypeLoc::initializeLocal(ASTContext &Context, setProtocolLoc(i, Loc); } +SourceRange AttributedTypeLoc::getLocalSourceRange() const { + // Note that this does *not* include the range of the attribute + // enclosure, e.g.: + // __attribute__((foo(bar))) + // ^~~~~~~~~~~~~~~ ~~ + // or + // [[foo(bar)]] + // ^~ ~~ + // That enclosure doesn't necessarily belong to a single attribute + // anyway. + return getAttr() ? getAttr()->getRange() : SourceRange(); +} + void TypeOfTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) { TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index dacbf9a96d81..c2f4baec989e 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1189,8 +1189,8 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) { if (PLoc.isValid()) { OS << " at "; StringRef File = PLoc.getFilename(); - if (Policy.RemapFilePaths) - OS << Policy.remapPath(File); + if (auto *Callbacks = Policy.Callbacks) + OS << Callbacks->remapPath(File); else OS << File; OS << ':' << PLoc.getLine() << ':' << PLoc.getColumn(); @@ -1555,6 +1555,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, case attr::NoDeref: OS << "noderef"; break; + case attr::AcquireHandle: + OS << "acquire_handle"; + break; } OS << "))"; } @@ -1772,6 +1775,37 @@ bool Qualifiers::isEmptyWhenPrinted(const PrintingPolicy &Policy) const { return true; } +std::string Qualifiers::getAddrSpaceAsString(LangAS AS) { + switch (AS) { + case LangAS::Default: + return ""; + case LangAS::opencl_global: + return "__global"; + case LangAS::opencl_local: + return "__local"; + case LangAS::opencl_private: + return "__private"; + case LangAS::opencl_constant: + return "__constant"; + case LangAS::opencl_generic: + return "__generic"; + case LangAS::cuda_device: + return "__device__"; + case LangAS::cuda_constant: + return "__constant__"; + case LangAS::cuda_shared: + return "__shared__"; + case LangAS::ptr32_sptr: + return "__sptr __ptr32"; + case LangAS::ptr32_uptr: + return "__uptr __ptr32"; + case LangAS::ptr64: + return "__ptr64"; + default: + return std::to_string(toTargetAddressSpace(AS)); + } +} + // Appends qualifiers to the given string, separated by spaces. Will // prefix a space if the string is non-empty. Will not append a final // space. @@ -1790,43 +1824,18 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy, OS << "__unaligned"; addSpace = true; } - LangAS addrspace = getAddressSpace(); - if (addrspace != LangAS::Default) { - if (addrspace != LangAS::opencl_private) { - if (addSpace) - OS << ' '; - addSpace = true; - switch (addrspace) { - case LangAS::opencl_global: - OS << "__global"; - break; - case LangAS::opencl_local: - OS << "__local"; - break; - case LangAS::opencl_private: - break; - case LangAS::opencl_constant: - OS << "__constant"; - break; - case LangAS::opencl_generic: - OS << "__generic"; - break; - case LangAS::cuda_device: - OS << "__device__"; - break; - case LangAS::cuda_constant: - OS << "__constant__"; - break; - case LangAS::cuda_shared: - OS << "__shared__"; - break; - default: - OS << "__attribute__((address_space("; - OS << toTargetAddressSpace(addrspace); - OS << ")))"; - } - } + auto ASStr = getAddrSpaceAsString(getAddressSpace()); + if (!ASStr.empty()) { + if (addSpace) + OS << ' '; + addSpace = true; + // Wrap target address space into an attribute syntax + if (isTargetAddressSpace(getAddressSpace())) + OS << "__attribute__((address_space(" << ASStr << ")))"; + else + OS << ASStr; } + if (Qualifiers::GC gc = getObjCGCAttr()) { if (addSpace) OS << ' '; diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp index 5688042dadd9..2b5b74be5961 100644 --- a/clang/lib/AST/VTableBuilder.cpp +++ b/clang/lib/AST/VTableBuilder.cpp @@ -270,8 +270,8 @@ static BaseOffset ComputeReturnAdjustmentBaseOffset(ASTContext &Context, const CXXMethodDecl *DerivedMD, const CXXMethodDecl *BaseMD) { - const FunctionType *BaseFT = BaseMD->getType()->getAs<FunctionType>(); - const FunctionType *DerivedFT = DerivedMD->getType()->getAs<FunctionType>(); + const auto *BaseFT = BaseMD->getType()->castAs<FunctionType>(); + const auto *DerivedFT = DerivedMD->getType()->castAs<FunctionType>(); // Canonicalize the return types. CanQualType CanDerivedReturnType = |