aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST')
-rw-r--r--clang/lib/AST/ASTConcept.cpp2
-rw-r--r--clang/lib/AST/ASTContext.cpp27
-rw-r--r--clang/lib/AST/ASTImporter.cpp4
-rw-r--r--clang/lib/AST/ASTStructuralEquivalence.cpp3
-rw-r--r--clang/lib/AST/ByteCode/ByteCodeEmitter.cpp47
-rw-r--r--clang/lib/AST/ByteCode/ByteCodeEmitter.h3
-rw-r--r--clang/lib/AST/ByteCode/Compiler.cpp91
-rw-r--r--clang/lib/AST/ByteCode/Compiler.h2
-rw-r--r--clang/lib/AST/ByteCode/Context.cpp11
-rw-r--r--clang/lib/AST/ByteCode/Context.h2
-rw-r--r--clang/lib/AST/ByteCode/Descriptor.cpp46
-rw-r--r--clang/lib/AST/ByteCode/EvalEmitter.cpp13
-rw-r--r--clang/lib/AST/ByteCode/EvalEmitter.h1
-rw-r--r--clang/lib/AST/ByteCode/Function.cpp1
-rw-r--r--clang/lib/AST/ByteCode/Function.h6
-rw-r--r--clang/lib/AST/ByteCode/Interp.cpp50
-rw-r--r--clang/lib/AST/ByteCode/Interp.h15
-rw-r--r--clang/lib/AST/ByteCode/InterpFrame.cpp12
-rw-r--r--clang/lib/AST/ByteCode/InterpShared.cpp18
-rw-r--r--clang/lib/AST/ByteCode/InterpState.cpp24
-rw-r--r--clang/lib/AST/ByteCode/PrimType.h1
-rw-r--r--clang/lib/AST/ByteCode/Program.cpp1
-rw-r--r--clang/lib/AST/ByteCode/State.cpp1
-rw-r--r--clang/lib/AST/ComputeDependence.cpp2
-rw-r--r--clang/lib/AST/Decl.cpp3
-rw-r--r--clang/lib/AST/DeclCXX.cpp2
-rw-r--r--clang/lib/AST/DeclPrinter.cpp8
-rw-r--r--clang/lib/AST/DeclTemplate.cpp39
-rw-r--r--clang/lib/AST/ExprCXX.cpp36
-rw-r--r--clang/lib/AST/ExprConstant.cpp2
-rw-r--r--clang/lib/AST/ItaniumMangle.cpp4
-rw-r--r--clang/lib/AST/Mangle.cpp4
-rw-r--r--clang/lib/AST/MicrosoftMangle.cpp3
-rw-r--r--clang/lib/AST/OpenACCClause.cpp31
-rw-r--r--clang/lib/AST/QualTypeNames.cpp2
-rw-r--r--clang/lib/AST/StmtProfile.cpp6
-rw-r--r--clang/lib/AST/TemplateBase.cpp11
-rw-r--r--clang/lib/AST/Type.cpp7
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);