diff options
Diffstat (limited to 'clang/lib/AST')
38 files changed, 366 insertions, 175 deletions
diff --git a/clang/lib/AST/ASTConcept.cpp b/clang/lib/AST/ASTConcept.cpp index 91ab66f..2243ac0 100644 --- a/clang/lib/AST/ASTConcept.cpp +++ b/clang/lib/AST/ASTConcept.cpp @@ -86,7 +86,7 @@ ConceptReference * ConceptReference::Create(const ASTContext &C, NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, - NamedDecl *FoundDecl, ConceptDecl *NamedConcept, + NamedDecl *FoundDecl, TemplateDecl *NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten) { return new (C) ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl, NamedConcept, ArgsAsWritten); diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 16cf114..3a16111 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -80,6 +80,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" #include "llvm/Support/Capacity.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MD5.h" @@ -717,13 +718,13 @@ comments::FullComment *ASTContext::getCommentForDecl( return FC; } -void -ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID, - const ASTContext &C, - TemplateTemplateParmDecl *Parm) { +void ASTContext::CanonicalTemplateTemplateParm::Profile( + llvm::FoldingSetNodeID &ID, const ASTContext &C, + TemplateTemplateParmDecl *Parm) { ID.AddInteger(Parm->getDepth()); ID.AddInteger(Parm->getPosition()); ID.AddBoolean(Parm->isParameterPack()); + ID.AddInteger(Parm->templateParameterKind()); TemplateParameterList *Params = Parm->getTemplateParameters(); ID.AddInteger(Params->size()); @@ -829,7 +830,9 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( TemplateTemplateParmDecl *CanonTTP = TemplateTemplateParmDecl::Create( *this, getTranslationUnitDecl(), SourceLocation(), TTP->getDepth(), - TTP->getPosition(), TTP->isParameterPack(), nullptr, /*Typename=*/false, + TTP->getPosition(), TTP->isParameterPack(), nullptr, + TTP->templateParameterKind(), + /*Typename=*/false, TemplateParameterList::Create(*this, SourceLocation(), SourceLocation(), CanonParams, SourceLocation(), /*RequiresClause=*/nullptr)); @@ -6643,7 +6646,7 @@ ASTContext::getUnaryTransformType(QualType BaseType, QualType UnderlyingType, QualType ASTContext::getAutoTypeInternal( QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent, - bool IsPack, ConceptDecl *TypeConstraintConcept, + bool IsPack, TemplateDecl *TypeConstraintConcept, ArrayRef<TemplateArgument> TypeConstraintArgs, bool IsCanon) const { if (DeducedType.isNull() && Keyword == AutoTypeKeyword::Auto && !TypeConstraintConcept && !IsDependent) @@ -6652,7 +6655,8 @@ QualType ASTContext::getAutoTypeInternal( // Look in the folding set for an existing type. llvm::FoldingSetNodeID ID; bool IsDeducedDependent = - !DeducedType.isNull() && DeducedType->isDependentType(); + isa_and_nonnull<TemplateTemplateParmDecl>(TypeConstraintConcept) || + (!DeducedType.isNull() && DeducedType->isDependentType()); AutoType::Profile(ID, *this, DeducedType, Keyword, IsDependent || IsDeducedDependent, TypeConstraintConcept, TypeConstraintArgs); @@ -6665,7 +6669,8 @@ QualType ASTContext::getAutoTypeInternal( Canon = DeducedType.getCanonicalType(); } else if (TypeConstraintConcept) { bool AnyNonCanonArgs = false; - ConceptDecl *CanonicalConcept = TypeConstraintConcept->getCanonicalDecl(); + auto *CanonicalConcept = + cast<TemplateDecl>(TypeConstraintConcept->getCanonicalDecl()); auto CanonicalConceptArgs = ::getCanonicalTemplateArguments( *this, TypeConstraintArgs, AnyNonCanonArgs); if (CanonicalConcept != TypeConstraintConcept || AnyNonCanonArgs) { @@ -6701,7 +6706,7 @@ QualType ASTContext::getAutoTypeInternal( QualType ASTContext::getAutoType(QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent, bool IsPack, - ConceptDecl *TypeConstraintConcept, + TemplateDecl *TypeConstraintConcept, ArrayRef<TemplateArgument> TypeConstraintArgs) const { assert((!IsPack || IsDependent) && "only use IsPack for a dependent pack"); assert((!IsDependent || DeducedType.isNull()) && @@ -14387,8 +14392,8 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X, if (KW != AY->getKeyword()) return QualType(); - ConceptDecl *CD = ::getCommonDecl(AX->getTypeConstraintConcept(), - AY->getTypeConstraintConcept()); + TemplateDecl *CD = ::getCommonDecl(AX->getTypeConstraintConcept(), + AY->getTypeConstraintConcept()); SmallVector<TemplateArgument, 8> As; if (CD && getCommonTemplateArguments(Ctx, As, AX->getTypeConstraintArguments(), diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index b9bdabe0b..8e2927b 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -6268,8 +6268,8 @@ ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { ToD, D, Importer.getToContext(), Importer.getToContext().getTranslationUnitDecl(), *LocationOrErr, D->getDepth(), D->getPosition(), D->isParameterPack(), - (*NameOrErr).getAsIdentifierInfo(), D->wasDeclaredWithTypename(), - *TemplateParamsOrErr)) + (*NameOrErr).getAsIdentifierInfo(), D->templateParameterKind(), + D->wasDeclaredWithTypename(), *TemplateParamsOrErr)) return ToD; if (Error Err = importTemplateParameterDefaultArgument(D, ToD)) diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index 22bb4cb..0e2023f 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -2313,7 +2313,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, } // Check template parameter lists. - return IsStructurallyEquivalent(Context, D1->getTemplateParameters(), + return D1->templateParameterKind() == D2->templateParameterKind() && + IsStructurallyEquivalent(Context, D1->getTemplateParameters(), D2->getTemplateParameters()); } diff --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp index 3288585..1d71708 100644 --- a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp +++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp @@ -135,25 +135,25 @@ int32_t ByteCodeEmitter::getOffset(LabelTy Label) { /// Helper to write bytecode and bail out if 32-bit offsets become invalid. /// Pointers will be automatically marshalled as 32-bit IDs. template <typename T> -static void emit(Program &P, std::vector<std::byte> &Code, const T &Val, - bool &Success) { +static void emit(Program &P, llvm::SmallVectorImpl<std::byte> &Code, + const T &Val, bool &Success) { + size_t ValPos = Code.size(); size_t Size; if constexpr (std::is_pointer_v<T>) - Size = sizeof(uint32_t); + Size = align(sizeof(uint32_t)); else - Size = sizeof(T); + Size = align(sizeof(T)); - if (Code.size() + Size > std::numeric_limits<unsigned>::max()) { + if (ValPos + Size > std::numeric_limits<unsigned>::max()) { Success = false; return; } // Access must be aligned! - size_t ValPos = align(Code.size()); - Size = align(Size); + assert(aligned(ValPos)); assert(aligned(ValPos + Size)); - Code.resize(ValPos + Size); + Code.resize_for_overwrite(ValPos + Size); if constexpr (!std::is_pointer_v<T>) { new (Code.data() + ValPos) T(Val); @@ -166,46 +166,45 @@ static void emit(Program &P, std::vector<std::byte> &Code, const T &Val, /// Emits a serializable value. These usually (potentially) contain /// heap-allocated memory and aren't trivially copyable. template <typename T> -static void emitSerialized(std::vector<std::byte> &Code, const T &Val, +static void emitSerialized(llvm::SmallVectorImpl<std::byte> &Code, const T &Val, bool &Success) { - size_t Size = Val.bytesToSerialize(); + size_t ValPos = Code.size(); + size_t Size = align(Val.bytesToSerialize()); - if (Code.size() + Size > std::numeric_limits<unsigned>::max()) { + if (ValPos + Size > std::numeric_limits<unsigned>::max()) { Success = false; return; } // Access must be aligned! - assert(aligned(Code.size())); - size_t ValPos = Code.size(); - Size = align(Size); + assert(aligned(ValPos)); assert(aligned(ValPos + Size)); - Code.resize(ValPos + Size); + Code.resize_for_overwrite(ValPos + Size); Val.serialize(Code.data() + ValPos); } template <> -void emit(Program &P, std::vector<std::byte> &Code, const Floating &Val, - bool &Success) { +void emit(Program &P, llvm::SmallVectorImpl<std::byte> &Code, + const Floating &Val, bool &Success) { emitSerialized(Code, Val, Success); } template <> -void emit(Program &P, std::vector<std::byte> &Code, +void emit(Program &P, llvm::SmallVectorImpl<std::byte> &Code, const IntegralAP<false> &Val, bool &Success) { emitSerialized(Code, Val, Success); } template <> -void emit(Program &P, std::vector<std::byte> &Code, const IntegralAP<true> &Val, - bool &Success) { +void emit(Program &P, llvm::SmallVectorImpl<std::byte> &Code, + const IntegralAP<true> &Val, bool &Success) { emitSerialized(Code, Val, Success); } template <> -void emit(Program &P, std::vector<std::byte> &Code, const FixedPoint &Val, - bool &Success) { +void emit(Program &P, llvm::SmallVectorImpl<std::byte> &Code, + const FixedPoint &Val, bool &Success) { emitSerialized(Code, Val, Success); } @@ -217,7 +216,9 @@ bool ByteCodeEmitter::emitOp(Opcode Op, const Tys &...Args, // The opcode is followed by arguments. The source info is // attached to the address after the opcode. emit(P, Code, Op, Success); - if (SI) + if (LocOverride) + SrcMap.emplace_back(Code.size(), *LocOverride); + else if (SI) SrcMap.emplace_back(Code.size(), SI); (..., emit(P, Code, Args, Success)); diff --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.h b/clang/lib/AST/ByteCode/ByteCodeEmitter.h index 9e9dd5e..d29db66 100644 --- a/clang/lib/AST/ByteCode/ByteCodeEmitter.h +++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.h @@ -73,6 +73,7 @@ protected: ParamOffset LambdaThisCapture{0, false}; /// Local descriptors. llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors; + std::optional<SourceInfo> LocOverride = std::nullopt; private: /// Current compilation context. @@ -88,7 +89,7 @@ private: /// Location of label relocations. llvm::DenseMap<LabelTy, llvm::SmallVector<unsigned, 5>> LabelRelocs; /// Program code. - std::vector<std::byte> Code; + llvm::SmallVector<std::byte> Code; /// Opcode to expression mapping. SourceMap SrcMap; diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 8b9e5e0..4ab4dee 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -185,6 +185,31 @@ private: bool OldFlag; }; +/// When generating code for e.g. implicit field initializers in constructors, +/// we don't have anything to point to in case the initializer causes an error. +/// In that case, we need to disable location tracking for the initializer so +/// we later point to the call range instead. +template <class Emitter> class LocOverrideScope final { +public: + LocOverrideScope(Compiler<Emitter> *Ctx, SourceInfo NewValue, + bool Enabled = true) + : Ctx(Ctx), OldFlag(Ctx->LocOverride), Enabled(Enabled) { + + if (Enabled) + Ctx->LocOverride = NewValue; + } + + ~LocOverrideScope() { + if (Enabled) + Ctx->LocOverride = OldFlag; + } + +private: + Compiler<Emitter> *Ctx; + std::optional<SourceInfo> OldFlag; + bool Enabled; +}; + } // namespace interp } // namespace clang @@ -201,6 +226,28 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) { return this->emitInvalidCast(CastKind::Volatile, /*Fatal=*/true, CE); OptPrimType SubExprT = classify(SubExpr->getType()); + // Try to load the value directly. This is purely a performance + // optimization. + if (SubExprT) { + if (const auto *DRE = dyn_cast<DeclRefExpr>(SubExpr)) { + const ValueDecl *D = DRE->getDecl(); + bool IsReference = D->getType()->isReferenceType(); + + if (!IsReference) { + if (Context::shouldBeGloballyIndexed(D)) { + if (auto GlobalIndex = P.getGlobal(D)) + return this->emitGetGlobal(*SubExprT, *GlobalIndex, CE); + } else if (auto It = Locals.find(D); It != Locals.end()) { + return this->emitGetLocal(*SubExprT, It->second.Offset, CE); + } else if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) { + if (auto It = this->Params.find(PVD); It != this->Params.end()) { + return this->emitGetParam(*SubExprT, It->second.Offset, CE); + } + } + } + } + } + // Prepare storage for the result. if (!Initializing && !SubExprT) { std::optional<unsigned> LocalIndex = allocateLocal(SubExpr); @@ -331,6 +378,8 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) { } case CK_FloatingToIntegral: { + if (!CE->getType()->isIntegralOrEnumerationType()) + return false; if (!this->visit(SubExpr)) return false; PrimType ToT = classifyPrim(CE); @@ -1369,10 +1418,15 @@ bool Compiler<Emitter>::VisitVectorBinOp(const BinaryOperator *E) { // BitAdd/BitOr/BitXor/Shl/Shr doesn't support bool type, we need perform the // integer promotion. bool NeedIntPromot = ElemT == PT_Bool && (E->isBitwiseOp() || E->isShiftOp()); - QualType PromotTy = - Ctx.getASTContext().getPromotedIntegerType(Ctx.getASTContext().BoolTy); - PrimType PromotT = classifyPrim(PromotTy); - PrimType OpT = NeedIntPromot ? PromotT : ElemT; + QualType PromotTy; + PrimType PromotT = PT_Bool; + PrimType OpT = ElemT; + if (NeedIntPromot) { + PromotTy = + Ctx.getASTContext().getPromotedIntegerType(Ctx.getASTContext().BoolTy); + PromotT = classifyPrim(PromotTy); + OpT = PromotT; + } auto getElem = [=](unsigned Offset, PrimType ElemT, unsigned Index) { if (!this->emitGetLocal(PT_Ptr, Offset, E)) @@ -2009,7 +2063,12 @@ bool Compiler<Emitter>::visitCallArgs(ArrayRef<const Expr *> Args, const FunctionDecl *FuncDecl, bool Activate) { assert(VarScope->getKind() == ScopeKind::Call); - llvm::BitVector NonNullArgs = collectNonNullArgs(FuncDecl, Args); + bool HasNonNullAttr = false; + llvm::BitVector NonNullArgs; + if (FuncDecl && FuncDecl->hasAttr<NonNullAttr>()) { + HasNonNullAttr = true; + NonNullArgs = collectNonNullArgs(FuncDecl, Args); + } unsigned ArgIndex = 0; for (const Expr *Arg : Args) { @@ -2035,7 +2094,7 @@ bool Compiler<Emitter>::visitCallArgs(ArrayRef<const Expr *> Args, return false; } - if (FuncDecl && NonNullArgs[ArgIndex]) { + if (HasNonNullAttr && NonNullArgs[ArgIndex]) { PrimType ArgT = classify(Arg).value_or(PT_Ptr); if (ArgT == PT_Ptr) { if (!this->emitCheckNonNullArg(ArgT, Arg)) @@ -3850,10 +3909,7 @@ template <class Emitter> bool Compiler<Emitter>::VisitAddrLabelExpr(const AddrLabelExpr *E) { assert(E->getType()->isVoidPointerType()); - unsigned Offset = - allocateLocalPrimitive(E->getLabel(), PT_Ptr, /*IsConst=*/true); - - return this->emitGetLocal(PT_Ptr, Offset, E); + return this->emitDummyPtr(E, E); } template <class Emitter> @@ -5888,7 +5944,7 @@ bool Compiler<Emitter>::emitLambdaStaticInvokerBody(const CXXMethodDecl *MD) { const CXXRecordDecl *ClosureClass = MD->getParent(); const CXXMethodDecl *LambdaCallOp = ClosureClass->getLambdaCallOperator(); - assert(ClosureClass->captures_begin() == ClosureClass->captures_end()); + assert(ClosureClass->captures().empty()); const Function *Func = this->getFunction(LambdaCallOp); if (!Func) return false; @@ -5986,6 +6042,8 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) { bool IsUnion = R->isUnion(); if (IsUnion && Ctor->isCopyOrMoveConstructor()) { + LocOverrideScope<Emitter> LOS(this, SourceInfo{}); + if (R->getNumFields() == 0) return this->emitRetVoid(Ctor); // union copy and move ctors are special. @@ -6012,6 +6070,11 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) { if (const FieldDecl *Member = Init->getMember()) { const Record::Field *F = R->getField(Member); + LocOverrideScope<Emitter> LOS(this, SourceInfo{}, + !Init->isWritten() && + !Init->isInClassMemberInitializer() && + (!isa<CXXConstructExpr>(InitExpr) || + Member->isAnonymousStructOrUnion())); if (!emitFieldInitializer(F, F->Offset, InitExpr, IsUnion)) return false; } else if (const Type *Base = Init->getBaseClass()) { @@ -6040,6 +6103,10 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) { if (!this->emitFinishInitPop(InitExpr)) return false; } else if (const IndirectFieldDecl *IFD = Init->getIndirectMember()) { + LocOverrideScope<Emitter> LOS(this, SourceInfo{}, + !Init->isWritten() && + !Init->isInClassMemberInitializer() && + !isa<CXXConstructExpr>(InitExpr)); assert(IFD->getChainingSize() >= 2); @@ -6118,6 +6185,8 @@ bool Compiler<Emitter>::compileDestructor(const CXXDestructorDecl *Dtor) { assert(R); if (!R->isUnion()) { + + LocOverrideScope<Emitter> LOS(this, SourceInfo{}); // First, destroy all fields. for (const Record::Field &Field : llvm::reverse(R->fields())) { const Descriptor *D = Field.Desc; diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h index 16f108f..ee8327d 100644 --- a/clang/lib/AST/ByteCode/Compiler.h +++ b/clang/lib/AST/ByteCode/Compiler.h @@ -40,6 +40,7 @@ template <class Emitter> class LoopScope; template <class Emitter> class LabelScope; template <class Emitter> class SwitchScope; template <class Emitter> class StmtExprScope; +template <class Emitter> class LocOverrideScope; template <class Emitter> class Compiler; struct InitLink { @@ -333,6 +334,7 @@ private: friend class LabelScope<Emitter>; friend class SwitchScope<Emitter>; friend class StmtExprScope<Emitter>; + friend class LocOverrideScope<Emitter>; /// Emits a zero initializer. bool visitZeroInitializer(PrimType T, QualType QT, const Expr *E); diff --git a/clang/lib/AST/ByteCode/Context.cpp b/clang/lib/AST/ByteCode/Context.cpp index aaeb52e..f7f528c 100644 --- a/clang/lib/AST/ByteCode/Context.cpp +++ b/clang/lib/AST/ByteCode/Context.cpp @@ -15,6 +15,7 @@ #include "InterpStack.h" #include "PrimType.h" #include "Program.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/Expr.h" #include "clang/Basic/TargetInfo.h" @@ -44,12 +45,12 @@ bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) { Compiler<ByteCodeEmitter>(*this, *P).compileFunc( FD, const_cast<Function *>(Func)); - ++EvalID; - // And run it. - if (!Run(Parent, Func)) + if (!Func->isValid()) return false; - return Func->isValid(); + ++EvalID; + // And run it. + return Run(Parent, Func); } void Context::isPotentialConstantExprUnevaluated(State &Parent, const Expr *E, @@ -473,7 +474,7 @@ const Function *Context::getOrCreateFunction(const FunctionDecl *FuncDecl) { IsLambdaStaticInvoker = true; const CXXRecordDecl *ClosureClass = MD->getParent(); - assert(ClosureClass->captures_begin() == ClosureClass->captures_end()); + assert(ClosureClass->captures().empty()); if (ClosureClass->isGenericLambda()) { const CXXMethodDecl *LambdaCallOp = ClosureClass->getLambdaCallOperator(); assert(MD->isFunctionTemplateSpecialization() && diff --git a/clang/lib/AST/ByteCode/Context.h b/clang/lib/AST/ByteCode/Context.h index 62ef529..1c084ac 100644 --- a/clang/lib/AST/ByteCode/Context.h +++ b/clang/lib/AST/ByteCode/Context.h @@ -17,9 +17,9 @@ #define LLVM_CLANG_AST_INTERP_CONTEXT_H #include "InterpStack.h" +#include "clang/AST/ASTContext.h" namespace clang { -class ASTContext; class LangOptions; class FunctionDecl; class VarDecl; diff --git a/clang/lib/AST/ByteCode/Descriptor.cpp b/clang/lib/AST/ByteCode/Descriptor.cpp index 5b9f445..7403e90 100644 --- a/clang/lib/AST/ByteCode/Descriptor.cpp +++ b/clang/lib/AST/ByteCode/Descriptor.cpp @@ -21,14 +21,31 @@ using namespace clang; using namespace clang::interp; +template <typename T> static constexpr bool needsCtor() { + if constexpr (std::is_same_v<T, Integral<8, true>> || + std::is_same_v<T, Integral<8, false>> || + std::is_same_v<T, Integral<16, true>> || + std::is_same_v<T, Integral<16, false>> || + std::is_same_v<T, Integral<32, true>> || + std::is_same_v<T, Integral<32, false>> || + std::is_same_v<T, Integral<64, true>> || + std::is_same_v<T, Integral<64, false>> || + std::is_same_v<T, Boolean>) + return false; + + return true; +} + template <typename T> static void ctorTy(Block *, std::byte *Ptr, bool, bool, bool, bool, bool, const Descriptor *) { + static_assert(needsCtor<T>()); new (Ptr) T(); } template <typename T> static void dtorTy(Block *, std::byte *Ptr, const Descriptor *) { + static_assert(needsCtor<T>()); reinterpret_cast<T *>(Ptr)->~T(); } @@ -45,9 +62,11 @@ static void ctorArrayTy(Block *, std::byte *Ptr, bool, bool, bool, bool, bool, const Descriptor *D) { new (Ptr) InitMapPtr(std::nullopt); - Ptr += sizeof(InitMapPtr); - for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) { - new (&reinterpret_cast<T *>(Ptr)[I]) T(); + if constexpr (needsCtor<T>()) { + Ptr += sizeof(InitMapPtr); + for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) { + new (&reinterpret_cast<T *>(Ptr)[I]) T(); + } } } @@ -57,9 +76,12 @@ static void dtorArrayTy(Block *, std::byte *Ptr, const Descriptor *D) { if (IMP) IMP = std::nullopt; - Ptr += sizeof(InitMapPtr); - for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) { - reinterpret_cast<T *>(Ptr)[I].~T(); + + if constexpr (needsCtor<T>()) { + Ptr += sizeof(InitMapPtr); + for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) { + reinterpret_cast<T *>(Ptr)[I].~T(); + } } } @@ -74,10 +96,14 @@ static void moveArrayTy(Block *, std::byte *Src, std::byte *Dst, } Src += sizeof(InitMapPtr); Dst += sizeof(InitMapPtr); - for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) { - auto *SrcPtr = &reinterpret_cast<T *>(Src)[I]; - auto *DstPtr = &reinterpret_cast<T *>(Dst)[I]; - new (DstPtr) T(std::move(*SrcPtr)); + if constexpr (!needsCtor<T>()) { + std::memcpy(Dst, Src, D->getNumElems() * D->getElemSize()); + } else { + for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) { + auto *SrcPtr = &reinterpret_cast<T *>(Src)[I]; + auto *DstPtr = &reinterpret_cast<T *>(Dst)[I]; + new (DstPtr) T(std::move(*SrcPtr)); + } } } diff --git a/clang/lib/AST/ByteCode/EvalEmitter.cpp b/clang/lib/AST/ByteCode/EvalEmitter.cpp index 81ebc56..976b7c0 100644 --- a/clang/lib/AST/ByteCode/EvalEmitter.cpp +++ b/clang/lib/AST/ByteCode/EvalEmitter.cpp @@ -53,6 +53,7 @@ EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD, bool CheckFullyInitialized) { this->CheckFullyInitialized = CheckFullyInitialized; S.EvaluatingDecl = VD; + S.setEvalLocation(VD->getLocation()); EvalResult.setSource(VD); if (const Expr *Init = VD->getAnyInitializer()) { @@ -233,6 +234,14 @@ template <> bool EvalEmitter::emitRet<PT_Ptr>(const SourceInfo &Info) { return false; } } else { + // If this is pointing to a local variable, just return + // the result, even if the pointer is dead. + // This will later be diagnosed by CheckLValueConstantExpression. + if (Ptr.isBlockPointer() && !Ptr.block()->isStatic()) { + EvalResult.setValue(Ptr.toAPValue(Ctx.getASTContext())); + return true; + } + if (!Ptr.isLive() && !Ptr.isTemporary()) return false; @@ -282,6 +291,10 @@ bool EvalEmitter::emitGetLocal(uint32_t I, const SourceInfo &Info) { using T = typename PrimConv<OpType>::T; Block *B = getLocal(I); + + if (!CheckLocalLoad(S, OpPC, Pointer(B))) + return false; + S.Stk.push<T>(*reinterpret_cast<T *>(B->data())); return true; } diff --git a/clang/lib/AST/ByteCode/EvalEmitter.h b/clang/lib/AST/ByteCode/EvalEmitter.h index 2fe7da6..85a0a99 100644 --- a/clang/lib/AST/ByteCode/EvalEmitter.h +++ b/clang/lib/AST/ByteCode/EvalEmitter.h @@ -95,6 +95,7 @@ protected: ParamOffset LambdaThisCapture{0, false}; /// Local descriptors. llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors; + std::optional<SourceInfo> LocOverride = std::nullopt; private: /// Current compilation context. diff --git a/clang/lib/AST/ByteCode/Function.cpp b/clang/lib/AST/ByteCode/Function.cpp index 0e639df3..a513be5 100644 --- a/clang/lib/AST/ByteCode/Function.cpp +++ b/clang/lib/AST/ByteCode/Function.cpp @@ -8,6 +8,7 @@ #include "Function.h" #include "Program.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" diff --git a/clang/lib/AST/ByteCode/Function.h b/clang/lib/AST/ByteCode/Function.h index de88f3d..92363b6 100644 --- a/clang/lib/AST/ByteCode/Function.h +++ b/clang/lib/AST/ByteCode/Function.h @@ -17,9 +17,9 @@ #include "Descriptor.h" #include "Source.h" -#include "clang/AST/ASTLambda.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/Support/raw_ostream.h" @@ -236,7 +236,7 @@ private: bool HasRVO, bool IsLambdaStaticInvoker); /// Sets the code of a function. - void setCode(unsigned NewFrameSize, std::vector<std::byte> &&NewCode, + void setCode(unsigned NewFrameSize, llvm::SmallVector<std::byte> &&NewCode, SourceMap &&NewSrcMap, llvm::SmallVector<Scope, 2> &&NewScopes, bool NewHasBody) { FrameSize = NewFrameSize; @@ -266,7 +266,7 @@ private: /// Size of the argument stack. unsigned ArgSize; /// Program code. - std::vector<std::byte> Code; + llvm::SmallVector<std::byte> Code; /// Opcode-to-expression mapping. SourceMap SrcMap; /// List of block descriptors. diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index 224d65c..eb4e480 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -715,23 +715,6 @@ static bool CheckLifetime(InterpState &S, CodePtr OpPC, const Pointer &Ptr, return false; } -bool CheckGlobalInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { - if (Ptr.isInitialized()) - return true; - - assert(S.getLangOpts().CPlusPlus); - const auto *VD = cast<VarDecl>(Ptr.getDeclDesc()->asValueDecl()); - if ((!VD->hasConstantInitialization() && - VD->mightBeUsableInConstantExpressions(S.getASTContext())) || - (S.getLangOpts().OpenCL && !S.getLangOpts().CPlusPlus11 && - !VD->hasICEInitializer(S.getASTContext()))) { - const SourceInfo &Loc = S.Current->getSource(OpPC); - S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD; - S.Note(VD->getLocation(), diag::note_declared_at); - } - return false; -} - static bool CheckWeak(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { if (!Ptr.isWeak()) return true; @@ -745,6 +728,39 @@ static bool CheckWeak(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { return false; } +// The list of checks here is just the one from CheckLoad, but with the +// ones removed that are impossible on primitive global values. +// For example, since those can't be members of structs, they also can't +// be mutable. +bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { + if (!CheckExtern(S, OpPC, Ptr)) + return false; + if (!CheckConstant(S, OpPC, Ptr)) + return false; + if (!CheckDummy(S, OpPC, Ptr, AK_Read)) + return false; + if (!CheckInitialized(S, OpPC, Ptr, AK_Read)) + return false; + if (!CheckTemporary(S, OpPC, Ptr, AK_Read)) + return false; + if (!CheckWeak(S, OpPC, Ptr)) + return false; + if (!CheckVolatile(S, OpPC, Ptr, AK_Read)) + return false; + return true; +} + +// Similarly, for local loads. +bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { + if (!CheckLifetime(S, OpPC, Ptr, AK_Read)) + return false; + if (!CheckInitialized(S, OpPC, Ptr, AK_Read)) + return false; + if (!CheckVolatile(S, OpPC, Ptr, AK_Read)) + return false; + return true; +} + bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK) { if (!CheckLive(S, OpPC, Ptr, AK)) diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 9a325ab..8a28106 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -91,8 +91,9 @@ bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr); bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK); -/// Check if a global variable is initialized. -bool CheckGlobalInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr); +/// Checks a direct load of a primitive value from a global or local variable. +bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr); +bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr); /// Checks if a value can be stored in a block. bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr); @@ -1351,7 +1352,7 @@ inline bool ConstFloat(InterpState &S, CodePtr OpPC, const Floating &F) { template <PrimType Name, class T = typename PrimConv<Name>::T> bool GetLocal(InterpState &S, CodePtr OpPC, uint32_t I) { const Pointer &Ptr = S.Current->getLocalPointer(I); - if (!CheckLoad(S, OpPC, Ptr)) + if (!CheckLocalLoad(S, OpPC, Ptr)) return false; S.Stk.push<T>(Ptr.deref<T>()); return true; @@ -1465,14 +1466,8 @@ bool SetThisField(InterpState &S, CodePtr OpPC, uint32_t I) { template <PrimType Name, class T = typename PrimConv<Name>::T> bool GetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) { const Pointer &Ptr = S.P.getPtrGlobal(I); - if (!CheckConstant(S, OpPC, Ptr.getFieldDesc())) - return false; - if (Ptr.isExtern()) - return false; - // If a global variable is uninitialized, that means the initializer we've - // compiled for it wasn't a constant expression. Diagnose that. - if (!CheckGlobalInitialized(S, OpPC, Ptr)) + if (!CheckGlobalLoad(S, OpPC, Ptr)) return false; S.Stk.push<T>(Ptr.deref<T>()); diff --git a/clang/lib/AST/ByteCode/InterpFrame.cpp b/clang/lib/AST/ByteCode/InterpFrame.cpp index d62a4f6..14f99c7 100644 --- a/clang/lib/AST/ByteCode/InterpFrame.cpp +++ b/clang/lib/AST/ByteCode/InterpFrame.cpp @@ -202,7 +202,17 @@ SourceRange InterpFrame::getCallRange() const { return NullRange; return S.EvalLocation; } - return S.getRange(Caller->Func, RetPC - sizeof(uintptr_t)); + + // Move up to the frame that has a valid location for the caller. + for (const InterpFrame *C = this; C; C = C->Caller) { + if (!C->RetPC) + continue; + SourceRange CallRange = + S.getRange(C->Caller->Func, C->RetPC - sizeof(uintptr_t)); + if (CallRange.isValid()) + return CallRange; + } + return S.EvalLocation; } const FunctionDecl *InterpFrame::getCallee() const { diff --git a/clang/lib/AST/ByteCode/InterpShared.cpp b/clang/lib/AST/ByteCode/InterpShared.cpp index 1e94dc1..e01b32b 100644 --- a/clang/lib/AST/ByteCode/InterpShared.cpp +++ b/clang/lib/AST/ByteCode/InterpShared.cpp @@ -16,23 +16,23 @@ namespace interp { llvm::BitVector collectNonNullArgs(const FunctionDecl *F, ArrayRef<const Expr *> Args) { llvm::BitVector NonNullArgs; - if (!F) - return NonNullArgs; assert(F); + assert(F->hasAttr<NonNullAttr>()); NonNullArgs.resize(Args.size()); for (const auto *Attr : F->specific_attrs<NonNullAttr>()) { if (!Attr->args_size()) { NonNullArgs.set(); break; - } else - for (auto Idx : Attr->args()) { - unsigned ASTIdx = Idx.getASTIndex(); - if (ASTIdx >= Args.size()) - continue; - NonNullArgs[ASTIdx] = true; - } + } + + for (auto Idx : Attr->args()) { + unsigned ASTIdx = Idx.getASTIndex(); + if (ASTIdx >= Args.size()) + continue; + NonNullArgs[ASTIdx] = true; + } } return NonNullArgs; diff --git a/clang/lib/AST/ByteCode/InterpState.cpp b/clang/lib/AST/ByteCode/InterpState.cpp index 3010847..a06b125 100644 --- a/clang/lib/AST/ByteCode/InterpState.cpp +++ b/clang/lib/AST/ByteCode/InterpState.cpp @@ -11,6 +11,8 @@ #include "InterpStack.h" #include "Program.h" #include "State.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" using namespace clang; using namespace clang::interp; @@ -77,27 +79,27 @@ void InterpState::deallocate(Block *B) { const Descriptor *Desc = B->getDescriptor(); assert(Desc); + // The block might have a pointer saved in a field in its data + // that points to the block itself. We call the dtor first, + // which will destroy all the data but leave InlineDescriptors + // intact. If the block THEN still has pointers, we create a + // DeadBlock for it. + if (B->IsInitialized) + B->invokeDtor(); + if (B->hasPointers()) { size_t Size = B->getSize(); - // Allocate a new block, transferring over pointers. char *Memory = reinterpret_cast<char *>(std::malloc(sizeof(DeadBlock) + Size)); auto *D = new (Memory) DeadBlock(DeadBlocks, B); - std::memset(D->B.rawData(), 0, D->B.getSize()); - - // Move data and metadata from the old block to the new (dead)block. - if (B->IsInitialized && Desc->MoveFn) { - Desc->MoveFn(B, B->data(), D->data(), Desc); - if (Desc->getMetadataSize() > 0) - std::memcpy(D->rawData(), B->rawData(), Desc->getMetadataSize()); - } + // Since the block doesn't hold any actual data anymore, we can just + // memcpy() everything over. + std::memcpy(D->rawData(), B->rawData(), Desc->getAllocSize()); D->B.IsInitialized = B->IsInitialized; // We moved the contents over to the DeadBlock. B->IsInitialized = false; - } else if (B->IsInitialized) { - B->invokeDtor(); } } diff --git a/clang/lib/AST/ByteCode/PrimType.h b/clang/lib/AST/ByteCode/PrimType.h index 38c29b9..724da93 100644 --- a/clang/lib/AST/ByteCode/PrimType.h +++ b/clang/lib/AST/ByteCode/PrimType.h @@ -13,7 +13,6 @@ #ifndef LLVM_CLANG_AST_INTERP_TYPE_H #define LLVM_CLANG_AST_INTERP_TYPE_H -#include "clang/Basic/UnsignedOrNone.h" #include "llvm/Support/raw_ostream.h" #include <climits> #include <cstddef> diff --git a/clang/lib/AST/ByteCode/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp index 2421ec4..4daa4ab 100644 --- a/clang/lib/AST/ByteCode/Program.cpp +++ b/clang/lib/AST/ByteCode/Program.cpp @@ -13,6 +13,7 @@ #include "PrimType.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" using namespace clang; using namespace clang::interp; diff --git a/clang/lib/AST/ByteCode/State.cpp b/clang/lib/AST/ByteCode/State.cpp index 3204d1a..dc3d0da 100644 --- a/clang/lib/AST/ByteCode/State.cpp +++ b/clang/lib/AST/ByteCode/State.cpp @@ -131,6 +131,7 @@ void State::addCallStack(unsigned Limit) { const Frame *Bottom = getBottomFrame(); for (const Frame *F = Top; F != Bottom; F = F->getCaller(), ++CallIdx) { SourceRange CallRange = F->getCallRange(); + assert(CallRange.isValid()); // Skip this call? if (CallIdx >= SkipStart && CallIdx < SkipEnd) { diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp index 14ec93e..87334d9 100644 --- a/clang/lib/AST/ComputeDependence.cpp +++ b/clang/lib/AST/ComputeDependence.cpp @@ -806,7 +806,7 @@ clang::computeDependence(OverloadExpr *E, bool KnownDependent, ~NestedNameSpecifierDependence::Dependent); for (auto *D : E->decls()) { if (D->getDeclContext()->isDependentContext() || - isa<UnresolvedUsingValueDecl>(D)) + isa<UnresolvedUsingValueDecl>(D) || isa<TemplateTemplateParmDecl>(D)) Deps |= ExprDependence::TypeValueInstantiation; } // If we have explicit template arguments, check for dependent diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 1588be4..5471f31 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -1233,6 +1233,9 @@ getExplicitVisibilityAux(const NamedDecl *ND, bool IsMostRecent) { assert(!IsMostRecent || ND == ND->getMostRecentDecl()); + if (isa<ConceptDecl>(ND)) + return {}; + // Check the declaration itself first. if (std::optional<Visibility> V = getVisibilityOf(ND, kind)) return V; diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 673e3f7..037a28c4 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -1983,7 +1983,7 @@ CXXRecordDecl::getVisibleConversionFunctions() const { ASTContext &Ctx = getASTContext(); ASTUnresolvedSet *Set; - if (bases_begin() == bases_end()) { + if (bases().empty()) { // If root class, all conversions are visible. Set = &data().Conversions.get(Ctx); } else { diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index 9273f58..f4265dd0 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -1443,7 +1443,7 @@ void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { lastPos = pos + 1; } - if (OMD->param_begin() == OMD->param_end()) + if (OMD->parameters().empty()) Out << name; if (OMD->isVariadic()) @@ -1480,8 +1480,7 @@ void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) { } Indentation -= Policy.Indentation; Out << "}\n"; - } - else if (SID || (OID->decls_begin() != OID->decls_end())) { + } else if (SID || !OID->decls().empty()) { Out << "\n"; eolnOut = true; } @@ -1540,8 +1539,7 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { } Indentation -= Policy.Indentation; Out << "}\n"; - } - else if (SID || (OID->decls_begin() != OID->decls_end())) { + } else if (SID || !OID->decls().empty()) { Out << "\n"; eolnOut = true; } diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 5035f2d..bc4a299 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -162,6 +162,7 @@ void TemplateParameterList::Profile(llvm::FoldingSetNodeID &ID, } const auto *TTP = cast<TemplateTemplateParmDecl>(D); ID.AddInteger(2); + ID.AddInteger(TTP->templateParameterKind()); ID.AddBoolean(TTP->isParameterPack()); TTP->getTemplateParameters()->Profile(ID, C); } @@ -184,7 +185,8 @@ unsigned TemplateParameterList::getMinRequiredArguments() const { } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) { if (NTTP->hasDefaultArgument()) break; - } else if (cast<TemplateTemplateParmDecl>(P)->hasDefaultArgument()) + } else if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P); + TTP && TTP->hasDefaultArgument()) break; ++NumRequiredArgs; @@ -873,38 +875,40 @@ void TemplateTemplateParmDecl::anchor() {} TemplateTemplateParmDecl::TemplateTemplateParmDecl( DeclContext *DC, SourceLocation L, unsigned D, unsigned P, - IdentifierInfo *Id, bool Typename, TemplateParameterList *Params, - ArrayRef<TemplateParameterList *> Expansions) + IdentifierInfo *Id, TemplateNameKind Kind, bool Typename, + TemplateParameterList *Params, ArrayRef<TemplateParameterList *> Expansions) : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params), - TemplateParmPosition(D, P), Typename(Typename), ParameterPack(true), - ExpandedParameterPack(true), NumExpandedParams(Expansions.size()) { + TemplateParmPosition(D, P), ParameterKind(Kind), Typename(Typename), + ParameterPack(true), ExpandedParameterPack(true), + NumExpandedParams(Expansions.size()) { llvm::uninitialized_copy(Expansions, getTrailingObjects()); } -TemplateTemplateParmDecl * -TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, - SourceLocation L, unsigned D, unsigned P, - bool ParameterPack, IdentifierInfo *Id, - bool Typename, TemplateParameterList *Params) { +TemplateTemplateParmDecl *TemplateTemplateParmDecl::Create( + const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, + unsigned P, bool ParameterPack, IdentifierInfo *Id, TemplateNameKind Kind, + bool Typename, TemplateParameterList *Params) { return new (C, DC) TemplateTemplateParmDecl(DC, L, D, P, ParameterPack, Id, - Typename, Params); + Kind, Typename, Params); } TemplateTemplateParmDecl * TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, unsigned P, - IdentifierInfo *Id, bool Typename, - TemplateParameterList *Params, + IdentifierInfo *Id, TemplateNameKind Kind, + bool Typename, TemplateParameterList *Params, ArrayRef<TemplateParameterList *> Expansions) { return new (C, DC, additionalSizeToAlloc<TemplateParameterList *>(Expansions.size())) - TemplateTemplateParmDecl(DC, L, D, P, Id, Typename, Params, Expansions); + TemplateTemplateParmDecl(DC, L, D, P, Id, Kind, Typename, Params, + Expansions); } TemplateTemplateParmDecl * TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) { - return new (C, ID) TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, - false, nullptr, false, nullptr); + return new (C, ID) TemplateTemplateParmDecl( + nullptr, SourceLocation(), 0, 0, false, nullptr, + TemplateNameKind::TNK_Type_template, false, nullptr); } TemplateTemplateParmDecl * @@ -913,7 +917,8 @@ TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID, auto *TTP = new (C, ID, additionalSizeToAlloc<TemplateParameterList *>(NumExpansions)) TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, nullptr, - false, nullptr, {}); + TemplateNameKind::TNK_Type_template, false, + nullptr, {}); TTP->NumExpandedParams = NumExpansions; return TTP; } diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 5833a64..a099e97 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -396,6 +396,16 @@ SourceLocation CXXPseudoDestructorExpr::getEndLoc() const { return End; } +static bool UnresolvedLookupExprIsVariableOrConceptParameterPack( + UnresolvedSetIterator Begin, UnresolvedSetIterator End) { + if (std::distance(Begin, End) != 1) + return false; + NamedDecl *ND = *Begin; + if (const auto *TTP = llvm::dyn_cast<TemplateTemplateParmDecl>(ND)) + return TTP->isParameterPack(); + return false; +} + // UnresolvedLookupExpr UnresolvedLookupExpr::UnresolvedLookupExpr( const ASTContext &Context, CXXRecordDecl *NamingClass, @@ -404,9 +414,11 @@ UnresolvedLookupExpr::UnresolvedLookupExpr( const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent, bool KnownInstantiationDependent) - : OverloadExpr(UnresolvedLookupExprClass, Context, QualifierLoc, - TemplateKWLoc, NameInfo, TemplateArgs, Begin, End, - KnownDependent, KnownInstantiationDependent, false), + : OverloadExpr( + UnresolvedLookupExprClass, Context, QualifierLoc, TemplateKWLoc, + NameInfo, TemplateArgs, Begin, End, KnownDependent, + KnownInstantiationDependent, + UnresolvedLookupExprIsVariableOrConceptParameterPack(Begin, End)), NamingClass(NamingClass) { UnresolvedLookupExprBits.RequiresADL = RequiresADL; } @@ -1714,8 +1726,8 @@ SizeOfPackExpr *SizeOfPackExpr::CreateDeserialized(ASTContext &Context, return new (Storage) SizeOfPackExpr(EmptyShell(), NumPartialArgs); } -NonTypeTemplateParmDecl *SubstNonTypeTemplateParmExpr::getParameter() const { - return cast<NonTypeTemplateParmDecl>( +NamedDecl *SubstNonTypeTemplateParmExpr::getParameter() const { + return cast<NamedDecl>( getReplacedTemplateParameterList(getAssociatedDecl())->asArray()[Index]); } @@ -1758,9 +1770,12 @@ QualType SubstNonTypeTemplateParmExpr::getParameterType( const ASTContext &Context) const { // Note that, for a class type NTTP, we will have an lvalue of type 'const // T', so we can't just compute this from the type and value category. + + QualType Type = getType(); + if (isReferenceParameter()) - return Context.getLValueReferenceType(getType()); - return getType().getUnqualifiedType(); + return Context.getLValueReferenceType(Type); + return Type.getUnqualifiedType(); } SubstNonTypeTemplateParmPackExpr::SubstNonTypeTemplateParmPackExpr( @@ -1997,9 +2012,10 @@ CXXFoldExpr::CXXFoldExpr(QualType T, UnresolvedLookupExpr *Callee, NumExpansions(NumExpansions) { CXXFoldExprBits.Opcode = Opcode; // We rely on asserted invariant to distinguish left and right folds. - assert(((LHS && LHS->containsUnexpandedParameterPack()) != - (RHS && RHS->containsUnexpandedParameterPack())) && - "Exactly one of LHS or RHS should contain an unexpanded pack"); + if (LHS && RHS) + assert(LHS->containsUnexpandedParameterPack() != + RHS->containsUnexpandedParameterPack() && + "Exactly one of LHS or RHS should contain an unexpanded pack"); SubExprs[SubExpr::Callee] = Callee; SubExprs[SubExpr::LHS] = LHS; SubExprs[SubExpr::RHS] = RHS; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 20b7c44..3a47fa8 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -8436,7 +8436,7 @@ public: // doesn't have an implicit argument passed in. const CXXRecordDecl *ClosureClass = MD->getParent(); assert( - ClosureClass->captures_begin() == ClosureClass->captures_end() && + ClosureClass->captures().empty() && "Number of captures must be zero for conversion to function-ptr"); const CXXMethodDecl *LambdaCallOp = diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 2a66793..5233648 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -529,7 +529,7 @@ private: void mangleUnqualifiedBlock(const BlockDecl *Block); void mangleTemplateParamDecl(const NamedDecl *Decl); void mangleTemplateParameterList(const TemplateParameterList *Params); - void mangleTypeConstraint(const ConceptDecl *Concept, + void mangleTypeConstraint(const TemplateDecl *Concept, ArrayRef<TemplateArgument> Arguments); void mangleTypeConstraint(const TypeConstraint *Constraint); void mangleRequiresClause(const Expr *RequiresClause); @@ -2080,7 +2080,7 @@ void CXXNameMangler::mangleTemplateParameterList( } void CXXNameMangler::mangleTypeConstraint( - const ConceptDecl *Concept, ArrayRef<TemplateArgument> Arguments) { + const TemplateDecl *Concept, ArrayRef<TemplateArgument> Arguments) { const DeclContext *DC = Context.getEffectiveDeclContext(Concept); if (!Arguments.empty()) mangleTemplateName(Concept, Arguments); diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp index 9652fdb..0bfb51c 100644 --- a/clang/lib/AST/Mangle.cpp +++ b/clang/lib/AST/Mangle.cpp @@ -161,9 +161,9 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) { if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) { // If we have an asm name, then we use it as the mangling. - // If the label isn't literal, or if this is an alias for an LLVM intrinsic, + // If the label is an alias for an LLVM intrinsic, // do not add a "\01" prefix. - if (!ALA->getIsLiteralLabel() || ALA->getLabel().starts_with("llvm.")) { + if (ALA->getLabel().starts_with("llvm.")) { Out << ALA->getLabel(); return; } diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index bc47e05..e6ea0ad 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -1298,8 +1298,7 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(GlobalDecl GD, Name += "<unnamed-type-"; Name += TND->getName(); } else if (isa<EnumDecl>(TD) && - cast<EnumDecl>(TD)->enumerator_begin() != - cast<EnumDecl>(TD)->enumerator_end()) { + !cast<EnumDecl>(TD)->enumerators().empty()) { // Anonymous non-empty enums mangle in the first enumerator. auto *ED = cast<EnumDecl>(TD); Name += "<unnamed-enum-"; diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp index 60ec10a..f7a98bd 100644 --- a/clang/lib/AST/OpenACCClause.cpp +++ b/clang/lib/AST/OpenACCClause.cpp @@ -314,23 +314,28 @@ OpenACCTileClause *OpenACCTileClause::Create(const ASTContext &C, return new (Mem) OpenACCTileClause(BeginLoc, LParenLoc, SizeExprs, EndLoc); } -OpenACCPrivateClause *OpenACCPrivateClause::Create(const ASTContext &C, - SourceLocation BeginLoc, - SourceLocation LParenLoc, - ArrayRef<Expr *> VarList, - SourceLocation EndLoc) { - void *Mem = C.Allocate( - OpenACCPrivateClause::totalSizeToAlloc<Expr *>(VarList.size())); - return new (Mem) OpenACCPrivateClause(BeginLoc, LParenLoc, VarList, EndLoc); +OpenACCPrivateClause * +OpenACCPrivateClause::Create(const ASTContext &C, SourceLocation BeginLoc, + SourceLocation LParenLoc, ArrayRef<Expr *> VarList, + ArrayRef<VarDecl *> InitRecipes, + SourceLocation EndLoc) { + assert(VarList.size() == InitRecipes.size()); + void *Mem = + C.Allocate(OpenACCPrivateClause::totalSizeToAlloc<Expr *, VarDecl *>( + VarList.size(), InitRecipes.size())); + return new (Mem) + OpenACCPrivateClause(BeginLoc, LParenLoc, VarList, InitRecipes, EndLoc); } OpenACCFirstPrivateClause *OpenACCFirstPrivateClause::Create( const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, - ArrayRef<Expr *> VarList, SourceLocation EndLoc) { - void *Mem = C.Allocate( - OpenACCFirstPrivateClause::totalSizeToAlloc<Expr *>(VarList.size())); - return new (Mem) - OpenACCFirstPrivateClause(BeginLoc, LParenLoc, VarList, EndLoc); + ArrayRef<Expr *> VarList, ArrayRef<VarDecl *> InitRecipes, + SourceLocation EndLoc) { + void *Mem = + C.Allocate(OpenACCFirstPrivateClause::totalSizeToAlloc<Expr *, VarDecl *>( + VarList.size(), InitRecipes.size())); + return new (Mem) OpenACCFirstPrivateClause(BeginLoc, LParenLoc, VarList, + InitRecipes, EndLoc); } OpenACCAttachClause *OpenACCAttachClause::Create(const ASTContext &C, diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp index b43bcd8..9731b3a 100644 --- a/clang/lib/AST/QualTypeNames.cpp +++ b/clang/lib/AST/QualTypeNames.cpp @@ -273,7 +273,7 @@ static NestedNameSpecifier *createNestedNameSpecifierForScopeOf( // // Make the situation is 'useable' but looking a bit odd by // picking a random instance as the declaring context. - if (ClassTempl->spec_begin() != ClassTempl->spec_end()) { + if (!ClassTempl->specializations().empty()) { Decl = *(ClassTempl->spec_begin()); Outer = dyn_cast<NamedDecl>(Decl); OuterNS = dyn_cast<NamespaceDecl>(Decl); diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index c61450e..4c36f24 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2636,11 +2636,17 @@ void OpenACCClauseProfiler::VisitCollapseClause( void OpenACCClauseProfiler::VisitPrivateClause( const OpenACCPrivateClause &Clause) { VisitClauseWithVarList(Clause); + + for (auto *VD : Clause.getInitRecipes()) + Profiler.VisitDecl(VD); } void OpenACCClauseProfiler::VisitFirstPrivateClause( const OpenACCFirstPrivateClause &Clause) { VisitClauseWithVarList(Clause); + + for (auto *VD : Clause.getInitRecipes()) + Profiler.VisitDecl(VD); } void OpenACCClauseProfiler::VisitAttachClause( diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp index 7c89dea..7a0f740 100644 --- a/clang/lib/AST/TemplateBase.cpp +++ b/clang/lib/AST/TemplateBase.cpp @@ -339,6 +339,17 @@ bool TemplateArgument::isPackExpansion() const { llvm_unreachable("Invalid TemplateArgument Kind!"); } +bool TemplateArgument::isConceptOrConceptTemplateParameter() const { + if (getKind() == TemplateArgument::Template) { + if (isa<ConceptDecl>(getAsTemplate().getAsTemplateDecl())) + return true; + else if (auto *TTP = dyn_cast_if_present<TemplateTemplateParmDecl>( + getAsTemplate().getAsTemplateDecl())) + return TTP->templateParameterKind() == TNK_Concept_template; + } + return false; +} + bool TemplateArgument::containsUnexpandedParameterPack() const { return getDependence() & TemplateArgumentDependence::UnexpandedPack; } diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 7444a2f..141edc8 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -5338,7 +5338,7 @@ void clang::FixedPointValueToString(SmallVectorImpl<char> &Str, AutoType::AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword, TypeDependence ExtraDependence, QualType Canon, - ConceptDecl *TypeConstraintConcept, + TemplateDecl *TypeConstraintConcept, ArrayRef<TemplateArgument> TypeConstraintArgs) : DeducedType(Auto, DeducedAsType, ExtraDependence, Canon) { AutoTypeBits.Keyword = llvm::to_underlying(Keyword); @@ -5346,6 +5346,9 @@ AutoType::AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword, this->TypeConstraintConcept = TypeConstraintConcept; assert(TypeConstraintConcept || AutoTypeBits.NumArgs == 0); if (TypeConstraintConcept) { + if (isa<TemplateTemplateParmDecl>(TypeConstraintConcept)) + addDependence(TypeDependence::DependentInstantiation); + auto *ArgBuffer = const_cast<TemplateArgument *>(getTypeConstraintArguments().data()); for (const TemplateArgument &Arg : TypeConstraintArgs) { @@ -5361,7 +5364,7 @@ AutoType::AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword, void AutoType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, QualType Deduced, AutoTypeKeyword Keyword, - bool IsDependent, ConceptDecl *CD, + bool IsDependent, TemplateDecl *CD, ArrayRef<TemplateArgument> Arguments) { ID.AddPointer(Deduced.getAsOpaquePtr()); ID.AddInteger((unsigned)Keyword); |