summaryrefslogtreecommitdiff
path: root/clang/lib/AST
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
commitcfca06d7963fa0909f90483b42a6d7d194d01e08 (patch)
tree209fb2a2d68f8f277793fc8df46c753d31bc853b /clang/lib/AST
parent706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff)
Notes
Diffstat (limited to 'clang/lib/AST')
-rw-r--r--clang/lib/AST/APValue.cpp84
-rw-r--r--clang/lib/AST/ASTConcept.cpp13
-rw-r--r--clang/lib/AST/ASTContext.cpp940
-rw-r--r--clang/lib/AST/ASTDiagnostic.cpp5
-rw-r--r--clang/lib/AST/ASTDumper.cpp95
-rw-r--r--clang/lib/AST/ASTImporter.cpp2152
-rw-r--r--clang/lib/AST/ASTImporterLookupTable.cpp6
-rw-r--r--clang/lib/AST/ASTStructuralEquivalence.cpp84
-rw-r--r--clang/lib/AST/ASTTypeTraits.cpp34
-rw-r--r--clang/lib/AST/AttrImpl.cpp151
-rw-r--r--clang/lib/AST/CXXInheritance.cpp26
-rw-r--r--clang/lib/AST/CommentCommandTraits.cpp1
-rw-r--r--clang/lib/AST/CommentSema.cpp50
-rw-r--r--clang/lib/AST/ComparisonCategories.cpp1
-rw-r--r--clang/lib/AST/ComputeDependence.cpp796
-rw-r--r--clang/lib/AST/DataCollection.cpp2
-rw-r--r--clang/lib/AST/Decl.cpp146
-rw-r--r--clang/lib/AST/DeclBase.cpp67
-rw-r--r--clang/lib/AST/DeclCXX.cpp268
-rw-r--r--clang/lib/AST/DeclObjC.cpp29
-rw-r--r--clang/lib/AST/DeclPrinter.cpp131
-rw-r--r--clang/lib/AST/DeclTemplate.cpp52
-rw-r--r--clang/lib/AST/DeclarationName.cpp16
-rw-r--r--clang/lib/AST/Expr.cpp1164
-rw-r--r--clang/lib/AST/ExprCXX.cpp488
-rw-r--r--clang/lib/AST/ExprClassification.cpp14
-rw-r--r--clang/lib/AST/ExprConcepts.cpp215
-rw-r--r--clang/lib/AST/ExprConstant.cpp864
-rw-r--r--clang/lib/AST/ExprObjC.cpp61
-rw-r--r--clang/lib/AST/ExternalASTSource.cpp19
-rw-r--r--clang/lib/AST/FormatString.cpp3
-rw-r--r--clang/lib/AST/Interp/Boolean.h7
-rw-r--r--clang/lib/AST/Interp/ByteCodeExprGen.h1
-rw-r--r--clang/lib/AST/Interp/Context.cpp1
-rw-r--r--clang/lib/AST/Interp/Disasm.cpp1
-rw-r--r--clang/lib/AST/Interp/Integral.h33
-rw-r--r--clang/lib/AST/Interp/Interp.cpp2
-rw-r--r--clang/lib/AST/Interp/Interp.h2
-rw-r--r--clang/lib/AST/Interp/InterpBlock.cpp (renamed from clang/lib/AST/Interp/Block.cpp)2
-rw-r--r--clang/lib/AST/Interp/InterpBlock.h (renamed from clang/lib/AST/Interp/Block.h)2
-rw-r--r--clang/lib/AST/Interp/InterpFrame.h8
-rw-r--r--clang/lib/AST/Interp/Pointer.cpp2
-rw-r--r--clang/lib/AST/Interp/Pointer.h4
-rw-r--r--clang/lib/AST/Interp/Source.h4
-rw-r--r--clang/lib/AST/ItaniumMangle.cpp373
-rw-r--r--clang/lib/AST/JSONNodeDumper.cpp91
-rw-r--r--clang/lib/AST/Linkage.h1
-rw-r--r--clang/lib/AST/Mangle.cpp74
-rw-r--r--clang/lib/AST/MicrosoftMangle.cpp170
-rw-r--r--clang/lib/AST/NSAPI.cpp4
-rw-r--r--clang/lib/AST/NestedNameSpecifier.cpp89
-rw-r--r--clang/lib/AST/ODRHash.cpp15
-rw-r--r--clang/lib/AST/OSLog.cpp6
-rw-r--r--clang/lib/AST/OpenMPClause.cpp655
-rw-r--r--clang/lib/AST/ParentMapContext.cpp321
-rw-r--r--clang/lib/AST/PrintfFormatString.cpp4
-rw-r--r--clang/lib/AST/RawCommentList.cpp3
-rw-r--r--clang/lib/AST/RecordLayoutBuilder.cpp38
-rw-r--r--clang/lib/AST/Stmt.cpp19
-rw-r--r--clang/lib/AST/StmtOpenMP.cpp101
-rw-r--r--clang/lib/AST/StmtPrinter.cpp200
-rw-r--r--clang/lib/AST/StmtProfile.cpp152
-rw-r--r--clang/lib/AST/TemplateBase.cpp142
-rw-r--r--clang/lib/AST/TemplateName.cpp70
-rw-r--r--clang/lib/AST/TextNodeDumper.cpp407
-rw-r--r--clang/lib/AST/Type.cpp479
-rw-r--r--clang/lib/AST/TypeLoc.cpp99
-rw-r--r--clang/lib/AST/TypePrinter.cpp114
-rw-r--r--clang/lib/AST/VTableBuilder.cpp154
69 files changed, 8020 insertions, 3807 deletions
diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp
index 50f8d05dacb4f..f3828bb54c1d3 100644
--- a/clang/lib/AST/APValue.cpp
+++ b/clang/lib/AST/APValue.cpp
@@ -378,11 +378,6 @@ void APValue::swap(APValue &RHS) {
memcpy(RHS.Data.buffer, TmpData, DataSize);
}
-LLVM_DUMP_METHOD void APValue::dump() const {
- dump(llvm::errs());
- llvm::errs() << '\n';
-}
-
static double GetApproxValue(const llvm::APFloat &F) {
llvm::APFloat V = F;
bool ignored;
@@ -391,85 +386,6 @@ static double GetApproxValue(const llvm::APFloat &F) {
return V.convertToDouble();
}
-void APValue::dump(raw_ostream &OS) const {
- switch (getKind()) {
- case None:
- OS << "None";
- return;
- case Indeterminate:
- OS << "Indeterminate";
- return;
- case Int:
- OS << "Int: " << getInt();
- return;
- case Float:
- OS << "Float: " << GetApproxValue(getFloat());
- return;
- case FixedPoint:
- OS << "FixedPoint : " << getFixedPoint();
- return;
- case Vector:
- OS << "Vector: ";
- getVectorElt(0).dump(OS);
- for (unsigned i = 1; i != getVectorLength(); ++i) {
- OS << ", ";
- getVectorElt(i).dump(OS);
- }
- return;
- case ComplexInt:
- OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag();
- return;
- case ComplexFloat:
- OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal())
- << ", " << GetApproxValue(getComplexFloatImag());
- return;
- case LValue:
- OS << "LValue: <todo>";
- return;
- case Array:
- OS << "Array: ";
- for (unsigned I = 0, N = getArrayInitializedElts(); I != N; ++I) {
- getArrayInitializedElt(I).dump(OS);
- if (I != getArraySize() - 1) OS << ", ";
- }
- if (hasArrayFiller()) {
- OS << getArraySize() - getArrayInitializedElts() << " x ";
- getArrayFiller().dump(OS);
- }
- return;
- case Struct:
- OS << "Struct ";
- if (unsigned N = getStructNumBases()) {
- OS << " bases: ";
- getStructBase(0).dump(OS);
- for (unsigned I = 1; I != N; ++I) {
- OS << ", ";
- getStructBase(I).dump(OS);
- }
- }
- if (unsigned N = getStructNumFields()) {
- OS << " fields: ";
- getStructField(0).dump(OS);
- for (unsigned I = 1; I != N; ++I) {
- OS << ", ";
- getStructField(I).dump(OS);
- }
- }
- return;
- case Union:
- OS << "Union: ";
- getUnionValue().dump(OS);
- return;
- case MemberPointer:
- OS << "MemberPointer: <todo>";
- return;
- case AddrLabelDiff:
- OS << "AddrLabelDiff: <todo>";
- return;
- }
- llvm_unreachable("Unknown APValue kind!");
-}
-
void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx,
QualType Ty) const {
switch (getKind()) {
diff --git a/clang/lib/AST/ASTConcept.cpp b/clang/lib/AST/ASTConcept.cpp
index fc32e768d92f8..549088ad4a8a8 100644
--- a/clang/lib/AST/ASTConcept.cpp
+++ b/clang/lib/AST/ASTConcept.cpp
@@ -14,6 +14,10 @@
#include "clang/AST/ASTConcept.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/TemplateBase.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/FoldingSet.h"
using namespace clang;
ASTConstraintSatisfaction::ASTConstraintSatisfaction(const ASTContext &C,
@@ -53,3 +57,12 @@ ASTConstraintSatisfaction::Create(const ASTContext &C,
void *Mem = C.Allocate(size, alignof(ASTConstraintSatisfaction));
return new (Mem) ASTConstraintSatisfaction(C, Satisfaction);
}
+
+void ConstraintSatisfaction::Profile(
+ llvm::FoldingSetNodeID &ID, const ASTContext &C,
+ const NamedDecl *ConstraintOwner, ArrayRef<TemplateArgument> TemplateArgs) {
+ ID.AddPointer(ConstraintOwner);
+ ID.AddInteger(TemplateArgs.size());
+ for (auto &Arg : TemplateArgs)
+ Arg.Profile(ID, C);
+}
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index a51429264dbee..2ba643f12a82f 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -29,15 +29,17 @@
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclarationName.h"
+#include "clang/AST/DependenceFlags.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprConcepts.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/MangleNumberingContext.h"
#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/ParentMapContext.h"
#include "clang/AST/RawCommentList.h"
#include "clang/AST/RecordLayout.h"
-#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/TemplateName.h"
@@ -54,6 +56,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Linkage.h"
+#include "clang/Basic/Module.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/SanitizerBlacklist.h"
#include "clang/Basic/SourceLocation.h"
@@ -97,34 +100,8 @@
using namespace clang;
enum FloatingRank {
- Float16Rank, HalfRank, FloatRank, DoubleRank, LongDoubleRank, Float128Rank
+ BFloat16Rank, Float16Rank, HalfRank, FloatRank, DoubleRank, LongDoubleRank, Float128Rank
};
-const Expr *ASTContext::traverseIgnored(const Expr *E) const {
- return traverseIgnored(const_cast<Expr *>(E));
-}
-
-Expr *ASTContext::traverseIgnored(Expr *E) const {
- if (!E)
- return nullptr;
-
- switch (Traversal) {
- case ast_type_traits::TK_AsIs:
- return E;
- case ast_type_traits::TK_IgnoreImplicitCastsAndParentheses:
- return E->IgnoreParenImpCasts();
- case ast_type_traits::TK_IgnoreUnlessSpelledInSource:
- return E->IgnoreUnlessSpelledInSource();
- }
- llvm_unreachable("Invalid Traversal type!");
-}
-
-ast_type_traits::DynTypedNode
-ASTContext::traverseIgnored(const ast_type_traits::DynTypedNode &N) const {
- if (const auto *E = N.get<Expr>()) {
- return ast_type_traits::DynTypedNode::create(*traverseIgnored(E));
- }
- return N;
-}
/// \returns location that is relevant when searching for Doc comments related
/// to \p D.
@@ -321,6 +298,12 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const {
return getRawCommentForDeclNoCacheImpl(D, DeclLoc, *CommentsInThisFile);
}
+void ASTContext::addComment(const RawComment &RC) {
+ assert(LangOpts.RetainCommentsFromSystemHeaders ||
+ !SourceMgr.isInSystemHeader(RC.getSourceRange().getBegin()));
+ Comments.addComment(RC, LangOpts.CommentOpts, BumpAlloc);
+}
+
/// If we have a 'templated' declaration for a template, adjust 'D' to
/// refer to the actual template.
/// If we have an implicit instantiation, adjust 'D' to refer to template.
@@ -493,10 +476,20 @@ void ASTContext::attachCommentsToJustParsedDecls(ArrayRef<Decl *> Decls,
if (Comments.empty() || Decls.empty())
return;
- // See if there are any new comments that are not attached to a decl.
- // The location doesn't have to be precise - we care only about the file.
- const FileID File =
- SourceMgr.getDecomposedLoc((*Decls.begin())->getLocation()).first;
+ FileID File;
+ for (Decl *D : Decls) {
+ SourceLocation Loc = D->getLocation();
+ if (Loc.isValid()) {
+ // See if there are any new comments that are not attached to a decl.
+ // The location doesn't have to be precise - we care only about the file.
+ File = SourceMgr.getDecomposedLoc(Loc).first;
+ break;
+ }
+ }
+
+ if (File.isInvalid())
+ return;
+
auto CommentsInThisFile = Comments.getCommentsInFile(File);
if (!CommentsInThisFile || CommentsInThisFile->empty() ||
CommentsInThisFile->rbegin()->second->isAttached())
@@ -661,7 +654,7 @@ comments::FullComment *ASTContext::getCommentForDecl(
return FC;
}
-void
+void
ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID,
const ASTContext &C,
TemplateTemplateParmDecl *Parm) {
@@ -716,6 +709,57 @@ ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID,
RequiresClause->Profile(ID, C, /*Canonical=*/true);
}
+static Expr *
+canonicalizeImmediatelyDeclaredConstraint(const ASTContext &C, Expr *IDC,
+ QualType ConstrainedType) {
+ // This is a bit ugly - we need to form a new immediately-declared
+ // constraint that references the new parameter; this would ideally
+ // require semantic analysis (e.g. template<C T> struct S {}; - the
+ // converted arguments of C<T> could be an argument pack if C is
+ // declared as template<typename... T> concept C = ...).
+ // We don't have semantic analysis here so we dig deep into the
+ // ready-made constraint expr and change the thing manually.
+ ConceptSpecializationExpr *CSE;
+ if (const auto *Fold = dyn_cast<CXXFoldExpr>(IDC))
+ CSE = cast<ConceptSpecializationExpr>(Fold->getLHS());
+ else
+ CSE = cast<ConceptSpecializationExpr>(IDC);
+ ArrayRef<TemplateArgument> OldConverted = CSE->getTemplateArguments();
+ SmallVector<TemplateArgument, 3> NewConverted;
+ NewConverted.reserve(OldConverted.size());
+ if (OldConverted.front().getKind() == TemplateArgument::Pack) {
+ // The case:
+ // template<typename... T> concept C = true;
+ // template<C<int> T> struct S; -> constraint is C<{T, int}>
+ NewConverted.push_back(ConstrainedType);
+ for (auto &Arg : OldConverted.front().pack_elements().drop_front(1))
+ NewConverted.push_back(Arg);
+ TemplateArgument NewPack(NewConverted);
+
+ NewConverted.clear();
+ NewConverted.push_back(NewPack);
+ assert(OldConverted.size() == 1 &&
+ "Template parameter pack should be the last parameter");
+ } else {
+ assert(OldConverted.front().getKind() == TemplateArgument::Type &&
+ "Unexpected first argument kind for immediately-declared "
+ "constraint");
+ NewConverted.push_back(ConstrainedType);
+ for (auto &Arg : OldConverted.drop_front(1))
+ NewConverted.push_back(Arg);
+ }
+ Expr *NewIDC = ConceptSpecializationExpr::Create(
+ C, CSE->getNamedConcept(), NewConverted, nullptr,
+ CSE->isInstantiationDependent(), CSE->containsUnexpandedParameterPack());
+
+ if (auto *OrigFold = dyn_cast<CXXFoldExpr>(IDC))
+ NewIDC = new (C) CXXFoldExpr(OrigFold->getType(), SourceLocation(), NewIDC,
+ BinaryOperatorKind::BO_LAnd,
+ SourceLocation(), /*RHS=*/nullptr,
+ SourceLocation(), /*NumExpansions=*/None);
+ return NewIDC;
+}
+
TemplateTemplateParmDecl *
ASTContext::getCanonicalTemplateTemplateParmDecl(
TemplateTemplateParmDecl *TTP) const {
@@ -743,68 +787,23 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
TTP->isExpandedParameterPack() ?
llvm::Optional<unsigned>(TTP->getNumExpansionParameters()) : None);
if (const auto *TC = TTP->getTypeConstraint()) {
- // This is a bit ugly - we need to form a new immediately-declared
- // constraint that references the new parameter; this would ideally
- // require semantic analysis (e.g. template<C T> struct S {}; - the
- // converted arguments of C<T> could be an argument pack if C is
- // declared as template<typename... T> concept C = ...).
- // We don't have semantic analysis here so we dig deep into the
- // ready-made constraint expr and change the thing manually.
- Expr *IDC = TC->getImmediatelyDeclaredConstraint();
- ConceptSpecializationExpr *CSE;
- if (const auto *Fold = dyn_cast<CXXFoldExpr>(IDC))
- CSE = cast<ConceptSpecializationExpr>(Fold->getLHS());
- else
- CSE = cast<ConceptSpecializationExpr>(IDC);
- ArrayRef<TemplateArgument> OldConverted = CSE->getTemplateArguments();
- SmallVector<TemplateArgument, 3> NewConverted;
- NewConverted.reserve(OldConverted.size());
-
QualType ParamAsArgument(NewTTP->getTypeForDecl(), 0);
- if (OldConverted.front().getKind() == TemplateArgument::Pack) {
- // The case:
- // template<typename... T> concept C = true;
- // template<C<int> T> struct S; -> constraint is C<{T, int}>
- NewConverted.push_back(ParamAsArgument);
- for (auto &Arg : OldConverted.front().pack_elements().drop_front(1))
- NewConverted.push_back(Arg);
- TemplateArgument NewPack(NewConverted);
-
- NewConverted.clear();
- NewConverted.push_back(NewPack);
- assert(OldConverted.size() == 1 &&
- "Template parameter pack should be the last parameter");
- } else {
- assert(OldConverted.front().getKind() == TemplateArgument::Type &&
- "Unexpected first argument kind for immediately-declared "
- "constraint");
- NewConverted.push_back(ParamAsArgument);
- for (auto &Arg : OldConverted.drop_front(1))
- NewConverted.push_back(Arg);
- }
- Expr *NewIDC = ConceptSpecializationExpr::Create(*this,
- NestedNameSpecifierLoc(), /*TemplateKWLoc=*/SourceLocation(),
- CSE->getConceptNameInfo(), /*FoundDecl=*/CSE->getNamedConcept(),
- CSE->getNamedConcept(),
- // Actually canonicalizing a TemplateArgumentLoc is difficult so we
- // simply omit the ArgsAsWritten
- /*ArgsAsWritten=*/nullptr, NewConverted, nullptr);
-
- if (auto *OrigFold = dyn_cast<CXXFoldExpr>(IDC))
- NewIDC = new (*this) CXXFoldExpr(OrigFold->getType(),
- SourceLocation(), NewIDC,
- BinaryOperatorKind::BO_LAnd,
- SourceLocation(), /*RHS=*/nullptr,
- SourceLocation(),
- /*NumExpansions=*/None);
-
+ Expr *NewIDC = canonicalizeImmediatelyDeclaredConstraint(
+ *this, TC->getImmediatelyDeclaredConstraint(),
+ ParamAsArgument);
+ TemplateArgumentListInfo CanonArgsAsWritten;
+ if (auto *Args = TC->getTemplateArgsAsWritten())
+ for (const auto &ArgLoc : Args->arguments())
+ CanonArgsAsWritten.addArgument(
+ TemplateArgumentLoc(ArgLoc.getArgument(),
+ TemplateArgumentLocInfo()));
NewTTP->setTypeConstraint(
NestedNameSpecifierLoc(),
DeclarationNameInfo(TC->getNamedConcept()->getDeclName(),
SourceLocation()), /*FoundDecl=*/nullptr,
// Actually canonicalizing a TemplateArgumentLoc is difficult so we
// simply omit the ArgsAsWritten
- CSE->getNamedConcept(), /*ArgsAsWritten=*/nullptr, NewIDC);
+ TC->getNamedConcept(), /*ArgsAsWritten=*/nullptr, NewIDC);
}
CanonParams.push_back(NewTTP);
} else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
@@ -839,6 +838,13 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
NTTP->isParameterPack(),
TInfo);
}
+ if (AutoType *AT = T->getContainedAutoType()) {
+ if (AT->isConstrained()) {
+ Param->setPlaceholderTypeConstraint(
+ canonicalizeImmediatelyDeclaredConstraint(
+ *this, NTTP->getPlaceholderTypeConstraint(), T));
+ }
+ }
CanonParams.push_back(Param);
} else
@@ -886,6 +892,7 @@ CXXABI *ASTContext::createCXXABI(const TargetInfo &T) {
case TargetCXXABI::GenericMIPS:
case TargetCXXABI::GenericItanium:
case TargetCXXABI::WebAssembly:
+ case TargetCXXABI::XL:
return CreateItaniumCXXABI(*this);
case TargetCXXABI::Microsoft:
return CreateMicrosoftCXXABI(*this);
@@ -900,6 +907,12 @@ interp::Context &ASTContext::getInterpContext() {
return *InterpContext.get();
}
+ParentMapContext &ASTContext::getParentMapContext() {
+ if (!ParentMapCtx)
+ ParentMapCtx.reset(new ParentMapContext(*this));
+ return *ParentMapCtx.get();
+}
+
static const LangASMap *getAddressSpaceMap(const TargetInfo &T,
const LangOptions &LOpts) {
if (LOpts.FakeAddressSpaceMap) {
@@ -943,7 +956,7 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
Builtin::Context &builtins)
: ConstantArrayTypes(this_()), FunctionProtoTypes(this_()),
TemplateSpecializationTypes(this_()),
- DependentTemplateSpecializationTypes(this_()),
+ DependentTemplateSpecializationTypes(this_()), AutoTypes(this_()),
SubstTemplateTemplateParmPacks(this_()),
CanonTemplateTemplateParms(this_()), SourceMgr(SM), LangOpts(LOpts),
SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)),
@@ -995,80 +1008,9 @@ ASTContext::~ASTContext() {
Value->~APValue();
}
-class ASTContext::ParentMap {
- /// Contains parents of a node.
- using ParentVector = llvm::SmallVector<ast_type_traits::DynTypedNode, 2>;
-
- /// Maps from a node to its parents. This is used for nodes that have
- /// pointer identity only, which are more common and we can save space by
- /// only storing a unique pointer to them.
- using ParentMapPointers = llvm::DenseMap<
- const void *,
- llvm::PointerUnion<const Decl *, const Stmt *,
- ast_type_traits::DynTypedNode *, ParentVector *>>;
-
- /// Parent map for nodes without pointer identity. We store a full
- /// DynTypedNode for all keys.
- using ParentMapOtherNodes = llvm::DenseMap<
- ast_type_traits::DynTypedNode,
- llvm::PointerUnion<const Decl *, const Stmt *,
- ast_type_traits::DynTypedNode *, ParentVector *>>;
-
- ParentMapPointers PointerParents;
- ParentMapOtherNodes OtherParents;
- class ASTVisitor;
-
- static ast_type_traits::DynTypedNode
- getSingleDynTypedNodeFromParentMap(ParentMapPointers::mapped_type U) {
- if (const auto *D = U.dyn_cast<const Decl *>())
- return ast_type_traits::DynTypedNode::create(*D);
- if (const auto *S = U.dyn_cast<const Stmt *>())
- return ast_type_traits::DynTypedNode::create(*S);
- return *U.get<ast_type_traits::DynTypedNode *>();
- }
-
- template <typename NodeTy, typename MapTy>
- static ASTContext::DynTypedNodeList getDynNodeFromMap(const NodeTy &Node,
- const MapTy &Map) {
- auto I = Map.find(Node);
- if (I == Map.end()) {
- return llvm::ArrayRef<ast_type_traits::DynTypedNode>();
- }
- if (const auto *V = I->second.template dyn_cast<ParentVector *>()) {
- return llvm::makeArrayRef(*V);
- }
- return getSingleDynTypedNodeFromParentMap(I->second);
- }
-
-public:
- ParentMap(ASTContext &Ctx);
- ~ParentMap() {
- for (const auto &Entry : PointerParents) {
- if (Entry.second.is<ast_type_traits::DynTypedNode *>()) {
- delete Entry.second.get<ast_type_traits::DynTypedNode *>();
- } else if (Entry.second.is<ParentVector *>()) {
- delete Entry.second.get<ParentVector *>();
- }
- }
- for (const auto &Entry : OtherParents) {
- if (Entry.second.is<ast_type_traits::DynTypedNode *>()) {
- delete Entry.second.get<ast_type_traits::DynTypedNode *>();
- } else if (Entry.second.is<ParentVector *>()) {
- delete Entry.second.get<ParentVector *>();
- }
- }
- }
-
- DynTypedNodeList getParents(const ast_type_traits::DynTypedNode &Node) {
- if (Node.getNodeKind().hasPointerIdentity())
- return getDynNodeFromMap(Node.getMemoizationData(), PointerParents);
- return getDynNodeFromMap(Node, OtherParents);
- }
-};
-
void ASTContext::setTraversalScope(const std::vector<Decl *> &TopLevelDecls) {
TraversalScope = TopLevelDecls;
- Parents.clear();
+ getParentMapContext().clear();
}
void ASTContext::AddDeallocation(void (*Callback)(void *), void *Data) const {
@@ -1163,6 +1105,15 @@ void ASTContext::deduplicateMergedDefinitonsFor(NamedDecl *ND) {
Merged.erase(std::remove(Merged.begin(), Merged.end(), nullptr), Merged.end());
}
+ArrayRef<Module *>
+ASTContext::getModulesWithMergedDefinition(const NamedDecl *Def) {
+ auto MergedIt =
+ MergedDefModules.find(cast<NamedDecl>(Def->getCanonicalDecl()));
+ if (MergedIt == MergedDefModules.end())
+ return None;
+ return MergedIt->second;
+}
+
void ASTContext::PerModuleInitializers::resolve(ASTContext &Ctx) {
if (LazyInitializers.empty())
return;
@@ -1432,8 +1383,13 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
InitBuiltinType(BuiltinFnTy, BuiltinType::BuiltinFn);
// Placeholder type for OMP array sections.
- if (LangOpts.OpenMP)
+ if (LangOpts.OpenMP) {
InitBuiltinType(OMPArraySectionTy, BuiltinType::OMPArraySection);
+ InitBuiltinType(OMPArrayShapingTy, BuiltinType::OMPArrayShaping);
+ InitBuiltinType(OMPIteratorTy, BuiltinType::OMPIterator);
+ }
+ if (LangOpts.MatrixTypes)
+ InitBuiltinType(IncompleteMatrixIdxTy, BuiltinType::IncompleteMatrixIdx);
// C99 6.2.5p11.
FloatComplexTy = getComplexType(FloatTy);
@@ -1492,8 +1448,16 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
// half type (OpenCL 6.1.1.1) / ARM NEON __fp16
InitBuiltinType(HalfTy, BuiltinType::Half);
+ InitBuiltinType(BFloat16Ty, BuiltinType::BFloat16);
+
// Builtin type used to help define __builtin_va_list.
VaListTagDecl = nullptr;
+
+ // MSVC predeclares struct _GUID, and we need it to create MSGuidDecls.
+ if (LangOpts.MicrosoftExt || LangOpts.Borland) {
+ MSGuidTagDecl = buildImplicitRecord("_GUID");
+ TUDecl->addDecl(MSGuidTagDecl);
+ }
}
DiagnosticsEngine &ASTContext::getDiagnostics() const {
@@ -1666,7 +1630,8 @@ void ASTContext::getOverriddenMethods(
}
void ASTContext::addedLocalImportDecl(ImportDecl *Import) {
- assert(!Import->NextLocalImport && "Import declaration already in the chain");
+ assert(!Import->getNextLocalImport() &&
+ "Import declaration already in the chain");
assert(!Import->isFromASTFile() && "Non-local import declaration");
if (!FirstLocalImport) {
FirstLocalImport = Import;
@@ -1674,7 +1639,7 @@ void ASTContext::addedLocalImportDecl(ImportDecl *Import) {
return;
}
- LastLocalImport->NextLocalImport = Import;
+ LastLocalImport->setNextLocalImport(Import);
LastLocalImport = Import;
}
@@ -1688,6 +1653,8 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
switch (T->castAs<BuiltinType>()->getKind()) {
default:
llvm_unreachable("Not a floating point type!");
+ case BuiltinType::BFloat16:
+ return Target->getBFloat16Format();
case BuiltinType::Float16:
case BuiltinType::Half:
return Target->getHalfFormat();
@@ -1800,6 +1767,10 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const {
return toCharUnitsFromBits(Align);
}
+CharUnits ASTContext::getExnObjectAlignment() const {
+ return toCharUnitsFromBits(Target->getExnObjectAlignment());
+}
+
// getTypeInfoDataSizeInChars - Return the size of a type, in
// chars. If the type is a record, its data size is returned. This is
// the size of the memcpy that's performed when assigning this type
@@ -1930,24 +1901,24 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
case Type::IncompleteArray:
case Type::VariableArray:
- Width = 0;
- Align = getTypeAlign(cast<ArrayType>(T)->getElementType());
- break;
-
case Type::ConstantArray: {
- const auto *CAT = cast<ConstantArrayType>(T);
+ // Model non-constant sized arrays as size zero, but track the alignment.
+ uint64_t Size = 0;
+ if (const auto *CAT = dyn_cast<ConstantArrayType>(T))
+ Size = CAT->getSize().getZExtValue();
- TypeInfo EltInfo = getTypeInfo(CAT->getElementType());
- uint64_t Size = CAT->getSize().getZExtValue();
+ TypeInfo EltInfo = getTypeInfo(cast<ArrayType>(T)->getElementType());
assert((Size == 0 || EltInfo.Width <= (uint64_t)(-1) / Size) &&
"Overflow in array type bit size evaluation");
Width = EltInfo.Width * Size;
Align = EltInfo.Align;
+ AlignIsRequired = EltInfo.AlignIsRequired;
if (!getTargetInfo().getCXXABI().isMicrosoft() ||
getTargetInfo().getPointerWidth(0) == 64)
Width = llvm::alignTo(Width, Align);
break;
}
+
case Type::ExtVector:
case Type::Vector: {
const auto *VT = cast<VectorType>(T);
@@ -1967,6 +1938,17 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
break;
}
+ case Type::ConstantMatrix: {
+ const auto *MT = cast<ConstantMatrixType>(T);
+ TypeInfo ElementInfo = getTypeInfo(MT->getElementType());
+ // The internal layout of a matrix value is implementation defined.
+ // Initially be ABI compatible with arrays with respect to alignment and
+ // size.
+ Width = ElementInfo.Width * MT->getNumRows() * MT->getNumColumns();
+ Align = ElementInfo.Align;
+ break;
+ }
+
case Type::Builtin:
switch (cast<BuiltinType>(T)->getKind()) {
default: llvm_unreachable("Unknown builtin type!");
@@ -2067,6 +2049,10 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
Width = Target->getLongFractWidth();
Align = Target->getLongFractAlign();
break;
+ case BuiltinType::BFloat16:
+ Width = Target->getBFloat16Width();
+ Align = Target->getBFloat16Align();
+ break;
case BuiltinType::Float16:
case BuiltinType::Half:
if (Target->hasFloat16Type() || !getLangOpts().OpenMP ||
@@ -2145,16 +2131,17 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
// Because the length is only known at runtime, we use a dummy value
// of 0 for the static length. The alignment values are those defined
// by the Procedure Call Standard for the Arm Architecture.
-#define SVE_VECTOR_TYPE(Name, Id, SingletonId, ElKind, ElBits, IsSigned, IsFP)\
- case BuiltinType::Id: \
- Width = 0; \
- Align = 128; \
- break;
-#define SVE_PREDICATE_TYPE(Name, Id, SingletonId, ElKind) \
- case BuiltinType::Id: \
- Width = 0; \
- Align = 16; \
- break;
+#define SVE_VECTOR_TYPE(Name, MangledName, Id, SingletonId, NumEls, ElBits, \
+ IsSigned, IsFP, IsBF) \
+ case BuiltinType::Id: \
+ Width = 0; \
+ Align = 128; \
+ break;
+#define SVE_PREDICATE_TYPE(Name, MangledName, Id, SingletonId, NumEls) \
+ case BuiltinType::Id: \
+ Width = 0; \
+ Align = 16; \
+ break;
#include "clang/Basic/AArch64SVEACLETypes.def"
}
break;
@@ -2202,11 +2189,25 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
return getTypeInfo(cast<AdjustedType>(T)->getAdjustedType().getTypePtr());
case Type::ObjCInterface: {
const auto *ObjCI = cast<ObjCInterfaceType>(T);
+ if (ObjCI->getDecl()->isInvalidDecl()) {
+ Width = 8;
+ Align = 8;
+ break;
+ }
const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl());
Width = toBits(Layout.getSize());
Align = toBits(Layout.getAlignment());
break;
}
+ case Type::ExtInt: {
+ const auto *EIT = cast<ExtIntType>(T);
+ Align =
+ std::min(static_cast<unsigned>(std::max(
+ getCharWidth(), llvm::PowerOf2Ceil(EIT->getNumBits()))),
+ Target->getLongLongAlign());
+ Width = llvm::alignTo(EIT->getNumBits(), Align);
+ break;
+ }
case Type::Record:
case Type::Enum: {
const auto *TT = cast<TagType>(T);
@@ -3383,6 +3384,8 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
case Type::DependentVector:
case Type::ExtVector:
case Type::DependentSizedExtVector:
+ case Type::ConstantMatrix:
+ case Type::DependentSizedMatrix:
case Type::DependentAddressSpace:
case Type::ObjCObject:
case Type::ObjCInterface:
@@ -3403,6 +3406,8 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
case Type::Auto:
case Type::DeducedTemplateSpecialization:
case Type::PackExpansion:
+ case Type::ExtInt:
+ case Type::DependentExtInt:
llvm_unreachable("type should never be variably-modified");
// These types can be variably-modified but should never need to
@@ -3629,6 +3634,33 @@ QualType ASTContext::getIncompleteArrayType(QualType elementType,
return QualType(newType, 0);
}
+/// getScalableVectorType - Return the unique reference to a scalable vector
+/// type of the specified element type and size. VectorType must be a built-in
+/// type.
+QualType ASTContext::getScalableVectorType(QualType EltTy,
+ unsigned NumElts) const {
+ if (Target->hasAArch64SVETypes()) {
+ uint64_t EltTySize = getTypeSize(EltTy);
+#define SVE_VECTOR_TYPE(Name, MangledName, Id, SingletonId, NumEls, ElBits, \
+ IsSigned, IsFP, IsBF) \
+ if (!EltTy->isBooleanType() && \
+ ((EltTy->hasIntegerRepresentation() && \
+ EltTy->hasSignedIntegerRepresentation() == IsSigned) || \
+ (EltTy->hasFloatingRepresentation() && !EltTy->isBFloat16Type() && \
+ IsFP && !IsBF) || \
+ (EltTy->hasFloatingRepresentation() && EltTy->isBFloat16Type() && \
+ IsBF && !IsFP)) && \
+ EltTySize == ElBits && NumElts == NumEls) { \
+ return SingletonId; \
+ }
+#define SVE_PREDICATE_TYPE(Name, MangledName, Id, SingletonId, NumEls) \
+ if (EltTy->isBooleanType() && NumElts == NumEls) \
+ return SingletonId;
+#include "clang/Basic/AArch64SVEACLETypes.def"
+ }
+ return QualType();
+}
+
/// getVectorType - Return the unique reference to a vector type of
/// the specified element type and size. VectorType must be a built-in type.
QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts,
@@ -3688,10 +3720,10 @@ ASTContext::getDependentVectorType(QualType VecType, Expr *SizeExpr,
(void)CanonCheck;
DependentVectorTypes.InsertNode(New, InsertPos);
} else {
- QualType CanonExtTy = getDependentSizedExtVectorType(CanonVecTy, SizeExpr,
- SourceLocation());
+ QualType CanonTy = getDependentVectorType(CanonVecTy, SizeExpr,
+ SourceLocation(), VecKind);
New = new (*this, TypeAlignment) DependentVectorType(
- *this, VecType, CanonExtTy, SizeExpr, AttrLoc, VecKind);
+ *this, VecType, CanonTy, SizeExpr, AttrLoc, VecKind);
}
}
@@ -3772,6 +3804,78 @@ ASTContext::getDependentSizedExtVectorType(QualType vecType,
return QualType(New, 0);
}
+QualType ASTContext::getConstantMatrixType(QualType ElementTy, unsigned NumRows,
+ unsigned NumColumns) const {
+ llvm::FoldingSetNodeID ID;
+ ConstantMatrixType::Profile(ID, ElementTy, NumRows, NumColumns,
+ Type::ConstantMatrix);
+
+ assert(MatrixType::isValidElementType(ElementTy) &&
+ "need a valid element type");
+ assert(ConstantMatrixType::isDimensionValid(NumRows) &&
+ ConstantMatrixType::isDimensionValid(NumColumns) &&
+ "need valid matrix dimensions");
+ void *InsertPos = nullptr;
+ if (ConstantMatrixType *MTP = MatrixTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(MTP, 0);
+
+ QualType Canonical;
+ if (!ElementTy.isCanonical()) {
+ Canonical =
+ getConstantMatrixType(getCanonicalType(ElementTy), NumRows, NumColumns);
+
+ ConstantMatrixType *NewIP = MatrixTypes.FindNodeOrInsertPos(ID, InsertPos);
+ assert(!NewIP && "Matrix type shouldn't already exist in the map");
+ (void)NewIP;
+ }
+
+ auto *New = new (*this, TypeAlignment)
+ ConstantMatrixType(ElementTy, NumRows, NumColumns, Canonical);
+ MatrixTypes.InsertNode(New, InsertPos);
+ Types.push_back(New);
+ return QualType(New, 0);
+}
+
+QualType ASTContext::getDependentSizedMatrixType(QualType ElementTy,
+ Expr *RowExpr,
+ Expr *ColumnExpr,
+ SourceLocation AttrLoc) const {
+ QualType CanonElementTy = getCanonicalType(ElementTy);
+ llvm::FoldingSetNodeID ID;
+ DependentSizedMatrixType::Profile(ID, *this, CanonElementTy, RowExpr,
+ ColumnExpr);
+
+ void *InsertPos = nullptr;
+ DependentSizedMatrixType *Canon =
+ DependentSizedMatrixTypes.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!Canon) {
+ Canon = new (*this, TypeAlignment) DependentSizedMatrixType(
+ *this, CanonElementTy, QualType(), RowExpr, ColumnExpr, AttrLoc);
+#ifndef NDEBUG
+ DependentSizedMatrixType *CanonCheck =
+ DependentSizedMatrixTypes.FindNodeOrInsertPos(ID, InsertPos);
+ assert(!CanonCheck && "Dependent-sized matrix canonical type broken");
+#endif
+ DependentSizedMatrixTypes.InsertNode(Canon, InsertPos);
+ Types.push_back(Canon);
+ }
+
+ // Already have a canonical version of the matrix type
+ //
+ // If it exactly matches the requested type, use it directly.
+ if (Canon->getElementType() == ElementTy && Canon->getRowExpr() == RowExpr &&
+ Canon->getRowExpr() == ColumnExpr)
+ return QualType(Canon, 0);
+
+ // Use Canon as the canonical type for newly-built type.
+ DependentSizedMatrixType *New = new (*this, TypeAlignment)
+ DependentSizedMatrixType(*this, ElementTy, QualType(Canon, 0), RowExpr,
+ ColumnExpr, AttrLoc);
+ Types.push_back(New);
+ return QualType(New, 0);
+}
+
QualType ASTContext::getDependentAddressSpaceType(QualType PointeeType,
Expr *AddrSpaceExpr,
SourceLocation AttrLoc) const {
@@ -4075,6 +4179,39 @@ QualType ASTContext::getWritePipeType(QualType T) const {
return getPipeType(T, false);
}
+QualType ASTContext::getExtIntType(bool IsUnsigned, unsigned NumBits) const {
+ llvm::FoldingSetNodeID ID;
+ ExtIntType::Profile(ID, IsUnsigned, NumBits);
+
+ void *InsertPos = nullptr;
+ if (ExtIntType *EIT = ExtIntTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(EIT, 0);
+
+ auto *New = new (*this, TypeAlignment) ExtIntType(IsUnsigned, NumBits);
+ ExtIntTypes.InsertNode(New, InsertPos);
+ Types.push_back(New);
+ return QualType(New, 0);
+}
+
+QualType ASTContext::getDependentExtIntType(bool IsUnsigned,
+ Expr *NumBitsExpr) const {
+ assert(NumBitsExpr->isInstantiationDependent() && "Only good for dependent");
+ llvm::FoldingSetNodeID ID;
+ DependentExtIntType::Profile(ID, *this, IsUnsigned, NumBitsExpr);
+
+ void *InsertPos = nullptr;
+ if (DependentExtIntType *Existing =
+ DependentExtIntTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(Existing, 0);
+
+ auto *New = new (*this, TypeAlignment)
+ DependentExtIntType(*this, IsUnsigned, NumBitsExpr);
+ DependentExtIntTypes.InsertNode(New, InsertPos);
+
+ Types.push_back(New);
+ return QualType(New, 0);
+}
+
#ifndef NDEBUG
static bool NeedsInjectedClassNameType(const RecordDecl *D) {
if (!isa<CXXRecordDecl>(D)) return false;
@@ -4587,7 +4724,7 @@ TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) {
} else if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
Expr *E = new (*this) DeclRefExpr(
*this, NTTP, /*enclosing*/ false,
- NTTP->getType().getNonLValueExprType(*this),
+ NTTP->getType().getNonPackExpansionType().getNonLValueExprType(*this),
Expr::getValueKindForType(NTTP->getType()), NTTP->getLocation());
if (NTTP->isParameterPack())
@@ -4859,7 +4996,7 @@ ASTContext::getObjCTypeParamType(const ObjCTypeParamDecl *Decl,
ArrayRef<ObjCProtocolDecl *> protocols) const {
// Look in the folding set for an existing type.
llvm::FoldingSetNodeID ID;
- ObjCTypeParamType::Profile(ID, Decl, protocols);
+ ObjCTypeParamType::Profile(ID, Decl, Decl->getUnderlyingType(), protocols);
void *InsertPos = nullptr;
if (ObjCTypeParamType *TypeParam =
ObjCTypeParamTypes.FindNodeOrInsertPos(ID, InsertPos))
@@ -4885,6 +5022,17 @@ ASTContext::getObjCTypeParamType(const ObjCTypeParamDecl *Decl,
return QualType(newType, 0);
}
+void ASTContext::adjustObjCTypeParamBoundType(const ObjCTypeParamDecl *Orig,
+ ObjCTypeParamDecl *New) const {
+ New->setTypeSourceInfo(getTrivialTypeSourceInfo(Orig->getUnderlyingType()));
+ // Update TypeForDecl after updating TypeSourceInfo.
+ auto NewTypeParamTy = cast<ObjCTypeParamType>(New->getTypeForDecl());
+ SmallVector<ObjCProtocolDecl *, 8> protocols;
+ protocols.append(NewTypeParamTy->qual_begin(), NewTypeParamTy->qual_end());
+ QualType UpdatedTy = getObjCTypeParamType(New, protocols);
+ New->setTypeForDecl(UpdatedTy.getTypePtr());
+}
+
/// ObjCObjectAdoptsQTypeProtocols - Checks that protocols in IC's
/// protocol list adopt all protocols in QT's qualified-id protocol
/// list.
@@ -5124,21 +5272,33 @@ QualType ASTContext::getUnaryTransformType(QualType BaseType,
/// getAutoType - Return the uniqued reference to the 'auto' type which has been
/// deduced to the given type, or to the canonical undeduced 'auto' type, or the
/// canonical deduced-but-dependent 'auto' type.
-QualType ASTContext::getAutoType(QualType DeducedType, AutoTypeKeyword Keyword,
- bool IsDependent, bool IsPack) const {
+QualType
+ASTContext::getAutoType(QualType DeducedType, AutoTypeKeyword Keyword,
+ bool IsDependent, bool IsPack,
+ ConceptDecl *TypeConstraintConcept,
+ ArrayRef<TemplateArgument> TypeConstraintArgs) const {
assert((!IsPack || IsDependent) && "only use IsPack for a dependent pack");
- if (DeducedType.isNull() && Keyword == AutoTypeKeyword::Auto && !IsDependent)
+ if (DeducedType.isNull() && Keyword == AutoTypeKeyword::Auto &&
+ !TypeConstraintConcept && !IsDependent)
return getAutoDeductType();
// Look in the folding set for an existing type.
void *InsertPos = nullptr;
llvm::FoldingSetNodeID ID;
- AutoType::Profile(ID, DeducedType, Keyword, IsDependent, IsPack);
+ AutoType::Profile(ID, *this, DeducedType, Keyword, IsDependent,
+ TypeConstraintConcept, TypeConstraintArgs);
if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(AT, 0);
- auto *AT = new (*this, TypeAlignment)
- AutoType(DeducedType, Keyword, IsDependent, IsPack);
+ void *Mem = Allocate(sizeof(AutoType) +
+ sizeof(TemplateArgument) * TypeConstraintArgs.size(),
+ TypeAlignment);
+ auto *AT = new (Mem) AutoType(
+ DeducedType, Keyword,
+ (IsDependent ? TypeDependence::DependentInstantiation
+ : TypeDependence::None) |
+ (IsPack ? TypeDependence::UnexpandedPack : TypeDependence::None),
+ TypeConstraintConcept, TypeConstraintArgs);
Types.push_back(AT);
if (InsertPos)
AutoTypes.InsertNode(AT, InsertPos);
@@ -5198,10 +5358,11 @@ QualType ASTContext::getAtomicType(QualType T) const {
/// getAutoDeductType - Get type pattern for deducing against 'auto'.
QualType ASTContext::getAutoDeductType() const {
if (AutoDeductTy.isNull())
- AutoDeductTy = QualType(
- new (*this, TypeAlignment) AutoType(QualType(), AutoTypeKeyword::Auto,
- /*dependent*/false, /*pack*/false),
- 0);
+ AutoDeductTy = QualType(new (*this, TypeAlignment)
+ AutoType(QualType(), AutoTypeKeyword::Auto,
+ TypeDependence::None,
+ /*concept*/ nullptr, /*args*/ {}),
+ 0);
return AutoDeductTy;
}
@@ -5837,6 +5998,7 @@ static FloatingRank getFloatingRank(QualType T) {
case BuiltinType::Double: return DoubleRank;
case BuiltinType::LongDouble: return LongDoubleRank;
case BuiltinType::Float128: return Float128Rank;
+ case BuiltinType::BFloat16: return BFloat16Rank;
}
}
@@ -5849,6 +6011,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size,
FloatingRank EltRank = getFloatingRank(Size);
if (Domain->isComplexType()) {
switch (EltRank) {
+ case BFloat16Rank: llvm_unreachable("Complex bfloat16 is not supported");
case Float16Rank:
case HalfRank: llvm_unreachable("Complex half is not supported");
case FloatRank: return FloatComplexTy;
@@ -5861,6 +6024,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size,
assert(Domain->isRealFloatingType() && "Unknown domain!");
switch (EltRank) {
case Float16Rank: return HalfTy;
+ case BFloat16Rank: return BFloat16Ty;
case HalfRank: return HalfTy;
case FloatRank: return FloatTy;
case DoubleRank: return DoubleTy;
@@ -5897,6 +6061,11 @@ int ASTContext::getFloatingTypeSemanticOrder(QualType LHS, QualType RHS) const {
unsigned ASTContext::getIntegerRank(const Type *T) const {
assert(T->isCanonicalUnqualified() && "T should be canonicalized");
+ // Results in this 'losing' to any type of the same size, but winning if
+ // larger.
+ if (const auto *EIT = dyn_cast<ExtIntType>(T))
+ return 0 + (EIT->getNumBits() << 3);
+
switch (cast<BuiltinType>(T)->getKind()) {
default: llvm_unreachable("getIntegerRank(): not a built-in integer");
case BuiltinType::Bool:
@@ -6287,39 +6456,39 @@ QualType ASTContext::getBlockDescriptorExtendedType() const {
return getTagDeclType(BlockDescriptorExtendedType);
}
-TargetInfo::OpenCLTypeKind ASTContext::getOpenCLTypeKind(const Type *T) const {
+OpenCLTypeKind ASTContext::getOpenCLTypeKind(const Type *T) const {
const auto *BT = dyn_cast<BuiltinType>(T);
if (!BT) {
if (isa<PipeType>(T))
- return TargetInfo::OCLTK_Pipe;
+ return OCLTK_Pipe;
- return TargetInfo::OCLTK_Default;
+ return OCLTK_Default;
}
switch (BT->getKind()) {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id: \
- return TargetInfo::OCLTK_Image;
+ return OCLTK_Image;
#include "clang/Basic/OpenCLImageTypes.def"
case BuiltinType::OCLClkEvent:
- return TargetInfo::OCLTK_ClkEvent;
+ return OCLTK_ClkEvent;
case BuiltinType::OCLEvent:
- return TargetInfo::OCLTK_Event;
+ return OCLTK_Event;
case BuiltinType::OCLQueue:
- return TargetInfo::OCLTK_Queue;
+ return OCLTK_Queue;
case BuiltinType::OCLReserveID:
- return TargetInfo::OCLTK_ReserveID;
+ return OCLTK_ReserveID;
case BuiltinType::OCLSampler:
- return TargetInfo::OCLTK_Sampler;
+ return OCLTK_Sampler;
default:
- return TargetInfo::OCLTK_Default;
+ return OCLTK_Default;
}
}
@@ -6392,6 +6561,24 @@ bool ASTContext::getByrefLifetime(QualType Ty,
return true;
}
+CanQualType ASTContext::getNSUIntegerType() const {
+ assert(Target && "Expected target to be initialized");
+ const llvm::Triple &T = Target->getTriple();
+ // Windows is LLP64 rather than LP64
+ if (T.isOSWindows() && T.isArch64Bit())
+ return UnsignedLongLongTy;
+ return UnsignedLongTy;
+}
+
+CanQualType ASTContext::getNSIntegerType() const {
+ assert(Target && "Expected target to be initialized");
+ const llvm::Triple &T = Target->getTriple();
+ // Windows is LLP64 rather than LP64
+ if (T.isOSWindows() && T.isArch64Bit())
+ return LongLongTy;
+ return LongTy;
+}
+
TypedefDecl *ASTContext::getObjCInstanceTypeDecl() {
if (!ObjCInstanceTypeDecl)
ObjCInstanceTypeDecl =
@@ -6695,11 +6882,11 @@ ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
if (PD->isReadOnly()) {
S += ",R";
- if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy)
+ if (PD->getPropertyAttributes() & ObjCPropertyAttribute::kind_copy)
S += ",C";
- if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain)
+ if (PD->getPropertyAttributes() & ObjCPropertyAttribute::kind_retain)
S += ",&";
- if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)
+ if (PD->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak)
S += ",W";
} else {
switch (PD->getSetterKind()) {
@@ -6715,15 +6902,15 @@ ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
if (Dynamic)
S += ",D";
- if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic)
+ if (PD->getPropertyAttributes() & ObjCPropertyAttribute::kind_nonatomic)
S += ",N";
- if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) {
+ if (PD->getPropertyAttributes() & ObjCPropertyAttribute::kind_getter) {
S += ",G";
S += PD->getGetterName().getAsString();
}
- if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) {
+ if (PD->getPropertyAttributes() & ObjCPropertyAttribute::kind_setter) {
S += ",S";
S += PD->getSetterName().getAsString();
}
@@ -6815,6 +7002,7 @@ static char getObjCEncodingForPrimitiveType(const ASTContext *C,
case BuiltinType::LongDouble: return 'D';
case BuiltinType::NullPtr: return '*'; // like char*
+ case BuiltinType::BFloat16:
case BuiltinType::Float16:
case BuiltinType::Float128:
case BuiltinType::Half:
@@ -7255,6 +7443,11 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S,
*NotEncodedT = T;
return;
+ case Type::ConstantMatrix:
+ if (NotEncodedT)
+ *NotEncodedT = T;
+ return;
+
// We could see an undeduced auto type here during error recovery.
// Just ignore it.
case Type::Auto:
@@ -7262,6 +7455,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S,
return;
case Type::Pipe:
+ case Type::ExtInt:
#define ABSTRACT_TYPE(KIND, BASE)
#define TYPE(KIND, BASE)
#define DEPENDENT_TYPE(KIND, BASE) \
@@ -7783,6 +7977,57 @@ CreateSystemZBuiltinVaListDecl(const ASTContext *Context) {
return Context->buildImplicitTypedef(VaListTagArrayType, "__builtin_va_list");
}
+static TypedefDecl *CreateHexagonBuiltinVaListDecl(const ASTContext *Context) {
+ // typedef struct __va_list_tag {
+ RecordDecl *VaListTagDecl;
+ VaListTagDecl = Context->buildImplicitRecord("__va_list_tag");
+ VaListTagDecl->startDefinition();
+
+ const size_t NumFields = 3;
+ QualType FieldTypes[NumFields];
+ const char *FieldNames[NumFields];
+
+ // void *CurrentSavedRegisterArea;
+ FieldTypes[0] = Context->getPointerType(Context->VoidTy);
+ FieldNames[0] = "__current_saved_reg_area_pointer";
+
+ // void *SavedRegAreaEnd;
+ FieldTypes[1] = Context->getPointerType(Context->VoidTy);
+ FieldNames[1] = "__saved_reg_area_end_pointer";
+
+ // void *OverflowArea;
+ FieldTypes[2] = Context->getPointerType(Context->VoidTy);
+ FieldNames[2] = "__overflow_area_pointer";
+
+ // Create fields
+ for (unsigned i = 0; i < NumFields; ++i) {
+ FieldDecl *Field = FieldDecl::Create(
+ const_cast<ASTContext &>(*Context), VaListTagDecl, SourceLocation(),
+ SourceLocation(), &Context->Idents.get(FieldNames[i]), FieldTypes[i],
+ /*TInfo=*/0,
+ /*BitWidth=*/0,
+ /*Mutable=*/false, ICIS_NoInit);
+ Field->setAccess(AS_public);
+ VaListTagDecl->addDecl(Field);
+ }
+ VaListTagDecl->completeDefinition();
+ Context->VaListTagDecl = VaListTagDecl;
+ QualType VaListTagType = Context->getRecordType(VaListTagDecl);
+
+ // } __va_list_tag;
+ TypedefDecl *VaListTagTypedefDecl =
+ Context->buildImplicitTypedef(VaListTagType, "__va_list_tag");
+
+ QualType VaListTagTypedefType = Context->getTypedefType(VaListTagTypedefDecl);
+
+ // typedef __va_list_tag __builtin_va_list[1];
+ llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 1);
+ QualType VaListTagArrayType = Context->getConstantArrayType(
+ VaListTagTypedefType, Size, nullptr, ArrayType::Normal, 0);
+
+ return Context->buildImplicitTypedef(VaListTagArrayType, "__builtin_va_list");
+}
+
static TypedefDecl *CreateVaListDecl(const ASTContext *Context,
TargetInfo::BuiltinVaListKind Kind) {
switch (Kind) {
@@ -7802,6 +8047,8 @@ static TypedefDecl *CreateVaListDecl(const ASTContext *Context,
return CreateAAPCSABIBuiltinVaListDecl(Context);
case TargetInfo::SystemZBuiltinVaList:
return CreateSystemZBuiltinVaListDecl(Context);
+ case TargetInfo::HexagonBuiltinVaList:
+ return CreateHexagonBuiltinVaListDecl(Context);
}
llvm_unreachable("Unhandled __builtin_va_list type kind");
@@ -8080,6 +8327,16 @@ static bool areCompatVectorTypes(const VectorType *LHS,
LHS->getNumElements() == RHS->getNumElements();
}
+/// areCompatMatrixTypes - Return true if the two specified matrix types are
+/// compatible.
+static bool areCompatMatrixTypes(const ConstantMatrixType *LHS,
+ const ConstantMatrixType *RHS) {
+ assert(LHS->isCanonicalUnqualified() && RHS->isCanonicalUnqualified());
+ return LHS->getElementType() == RHS->getElementType() &&
+ LHS->getNumRows() == RHS->getNumRows() &&
+ LHS->getNumColumns() == RHS->getNumColumns();
+}
+
bool ASTContext::areCompatibleVectorTypes(QualType FirstVec,
QualType SecondVec) {
assert(FirstVec->isVectorType() && "FirstVec should be a vector type");
@@ -8362,10 +8619,18 @@ bool ASTContext::canAssignObjCInterfacesInBlockPointer(
RHSOPT->isObjCQualifiedIdType());
}
- if (LHSOPT->isObjCQualifiedIdType() || RHSOPT->isObjCQualifiedIdType())
- return finish(ObjCQualifiedIdTypesAreCompatible(
- (BlockReturnType ? LHSOPT : RHSOPT),
- (BlockReturnType ? RHSOPT : LHSOPT), false));
+ if (LHSOPT->isObjCQualifiedIdType() || RHSOPT->isObjCQualifiedIdType()) {
+ if (getLangOpts().CompatibilityQualifiedIdBlockParamTypeChecking)
+ // Use for block parameters previous type checking for compatibility.
+ return finish(ObjCQualifiedIdTypesAreCompatible(LHSOPT, RHSOPT, false) ||
+ // Or corrected type checking as in non-compat mode.
+ (!BlockReturnType &&
+ ObjCQualifiedIdTypesAreCompatible(RHSOPT, LHSOPT, false)));
+ else
+ return finish(ObjCQualifiedIdTypesAreCompatible(
+ (BlockReturnType ? LHSOPT : RHSOPT),
+ (BlockReturnType ? RHSOPT : LHSOPT), false));
+ }
const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
@@ -8716,8 +8981,8 @@ bool ASTContext::areComparableObjCPointerTypes(QualType LHS, QualType RHS) {
bool ASTContext::canBindObjCObjectType(QualType To, QualType From) {
return canAssignObjCInterfaces(
- getObjCObjectPointerType(To)->getAs<ObjCObjectPointerType>(),
- getObjCObjectPointerType(From)->getAs<ObjCObjectPointerType>());
+ getObjCObjectPointerType(To)->castAs<ObjCObjectPointerType>(),
+ getObjCObjectPointerType(From)->castAs<ObjCObjectPointerType>());
}
/// typesAreCompatible - C99 6.7.3p9: For two qualified types to be compatible,
@@ -8783,8 +9048,8 @@ QualType ASTContext::mergeFunctionParameterTypes(QualType lhs, QualType rhs,
}
QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
- bool OfBlockPointer,
- bool Unqualified) {
+ bool OfBlockPointer, bool Unqualified,
+ bool AllowCXX) {
const auto *lbase = lhs->castAs<FunctionType>();
const auto *rbase = rhs->castAs<FunctionType>();
const auto *lproto = dyn_cast<FunctionProtoType>(lbase);
@@ -8858,7 +9123,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
FunctionType::ExtInfo einfo = lbaseInfo.withNoReturn(NoReturn);
if (lproto && rproto) { // two C99 style function prototypes
- assert(!lproto->hasExceptionSpec() && !rproto->hasExceptionSpec() &&
+ assert((AllowCXX ||
+ (!lproto->hasExceptionSpec() && !rproto->hasExceptionSpec())) &&
"C++ shouldn't be here");
// Compatible functions must have the same number of parameters
if (lproto->getNumParams() != rproto->getNumParams())
@@ -8922,7 +9188,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
const FunctionProtoType *proto = lproto ? lproto : rproto;
if (proto) {
- assert(!proto->hasExceptionSpec() && "C++ shouldn't be here");
+ assert((AllowCXX || !proto->hasExceptionSpec()) && "C++ shouldn't be here");
if (proto->isVariadic())
return {};
// Check that the types are compatible with the types that
@@ -9276,6 +9542,11 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
RHSCan->castAs<VectorType>()))
return LHS;
return {};
+ case Type::ConstantMatrix:
+ if (areCompatMatrixTypes(LHSCan->castAs<ConstantMatrixType>(),
+ RHSCan->castAs<ConstantMatrixType>()))
+ return LHS;
+ return {};
case Type::ObjCObject: {
// Check if the types are assignment compatible.
// FIXME: This should be type compatibility, e.g. whether
@@ -9301,6 +9572,21 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
assert(LHS != RHS &&
"Equivalent pipe types should have already been handled!");
return {};
+ case Type::ExtInt: {
+ // Merge two ext-int types, while trying to preserve typedef info.
+ bool LHSUnsigned = LHS->castAs<ExtIntType>()->isUnsigned();
+ bool RHSUnsigned = RHS->castAs<ExtIntType>()->isUnsigned();
+ unsigned LHSBits = LHS->castAs<ExtIntType>()->getNumBits();
+ unsigned RHSBits = RHS->castAs<ExtIntType>()->getNumBits();
+
+ // Like unsigned/int, shouldn't have a type if they dont match.
+ if (LHSUnsigned != RHSUnsigned)
+ return {};
+
+ if (LHSBits != RHSBits)
+ return {};
+ return LHS;
+ }
}
llvm_unreachable("Invalid Type::Class!");
@@ -9441,6 +9727,8 @@ unsigned ASTContext::getIntWidth(QualType T) const {
T = ET->getDecl()->getIntegerType();
if (T->isBooleanType())
return 1;
+ if(const auto *EIT = T->getAs<ExtIntType>())
+ return EIT->getNumBits();
// For builtin types, just use the standard type sizing method
return (unsigned)getTypeSize(T);
}
@@ -9622,6 +9910,11 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
// Read the base type.
switch (*Str++) {
default: llvm_unreachable("Unknown builtin type letter!");
+ case 'y':
+ assert(HowLong == 0 && !Signed && !Unsigned &&
+ "Bad modifiers used with 'y'!");
+ Type = Context.BFloat16Ty;
+ break;
case 'v':
assert(HowLong == 0 && !Signed && !Unsigned &&
"Bad modifiers used with 'v'!");
@@ -9717,6 +10010,19 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
else
Type = Context.getLValueReferenceType(Type);
break;
+ case 'q': {
+ char *End;
+ unsigned NumElements = strtoul(Str, &End, 10);
+ assert(End != Str && "Missing vector size");
+ Str = End;
+
+ QualType ElementType = DecodeTypeFromStr(Str, Context, Error,
+ RequiresICE, false);
+ assert(!RequiresICE && "Can't require vector ICE");
+
+ Type = Context.getScalableVectorType(ElementType, NumElements);
+ break;
+ }
case 'V': {
char *End;
unsigned NumElements = strtoul(Str, &End, 10);
@@ -10109,6 +10415,8 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
return true;
else if (isa<PragmaDetectMismatchDecl>(D))
return true;
+ else if (isa<OMPRequiresDecl>(D))
+ return true;
else if (isa<OMPThreadPrivateDecl>(D))
return !D->getDeclContext()->isDependentContext();
else if (isa<OMPAllocateDecl>(D))
@@ -10298,10 +10606,15 @@ bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) const {
VTableContextBase *ASTContext::getVTableContext() {
if (!VTContext.get()) {
- if (Target->getCXXABI().isMicrosoft())
+ auto ABI = Target->getCXXABI();
+ if (ABI.isMicrosoft())
VTContext.reset(new MicrosoftVTableContext(*this));
- else
- VTContext.reset(new ItaniumVTableContext(*this));
+ else {
+ auto ComponentLayout = getLangOpts().RelativeCXXABIVTables
+ ? ItaniumVTableContext::Relative
+ : ItaniumVTableContext::Pointer;
+ VTContext.reset(new ItaniumVTableContext(*this, ComponentLayout));
+ }
}
return VTContext.get();
}
@@ -10319,6 +10632,7 @@ MangleContext *ASTContext::createMangleContext(const TargetInfo *T) {
case TargetCXXABI::iOS64:
case TargetCXXABI::WebAssembly:
case TargetCXXABI::WatchOS:
+ case TargetCXXABI::XL:
return ItaniumMangleContext::create(*this, getDiagnostics());
case TargetCXXABI::Microsoft:
return MicrosoftMangleContext::create(*this, getDiagnostics());
@@ -10360,8 +10674,10 @@ QualType ASTContext::getIntTypeForBitwidth(unsigned DestWidth,
/// getRealTypeForBitwidth -
/// sets floating point QualTy according to specified bitwidth.
/// Returns empty type if there is no appropriate target types.
-QualType ASTContext::getRealTypeForBitwidth(unsigned DestWidth) const {
- TargetInfo::RealType Ty = getTargetInfo().getRealTypeByWidth(DestWidth);
+QualType ASTContext::getRealTypeForBitwidth(unsigned DestWidth,
+ bool ExplicitIEEE) const {
+ TargetInfo::RealType Ty =
+ getTargetInfo().getRealTypeByWidth(DestWidth, ExplicitIEEE);
switch (Ty) {
case TargetInfo::Float:
return FloatTy;
@@ -10490,6 +10806,23 @@ ASTContext::getPredefinedStringLiteralFromCache(StringRef Key) const {
return Result;
}
+MSGuidDecl *
+ASTContext::getMSGuidDecl(MSGuidDecl::Parts Parts) const {
+ assert(MSGuidTagDecl && "building MS GUID without MS extensions?");
+
+ llvm::FoldingSetNodeID ID;
+ MSGuidDecl::Profile(ID, Parts);
+
+ void *InsertPos;
+ if (MSGuidDecl *Existing = MSGuidDecls.FindNodeOrInsertPos(ID, InsertPos))
+ return Existing;
+
+ QualType GUIDType = getMSGuidType().withConst();
+ MSGuidDecl *New = MSGuidDecl::Create(*this, GUIDType, Parts);
+ MSGuidDecls.InsertNode(New, InsertPos);
+ return New;
+}
+
bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const {
const llvm::Triple &T = getTargetInfo().getTriple();
if (!T.isOSDarwin())
@@ -10508,146 +10841,6 @@ bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const {
return (Size != Align || toBits(sizeChars) > MaxInlineWidthInBits);
}
-/// Template specializations to abstract away from pointers and TypeLocs.
-/// @{
-template <typename T>
-static ast_type_traits::DynTypedNode createDynTypedNode(const T &Node) {
- return ast_type_traits::DynTypedNode::create(*Node);
-}
-template <>
-ast_type_traits::DynTypedNode createDynTypedNode(const TypeLoc &Node) {
- return ast_type_traits::DynTypedNode::create(Node);
-}
-template <>
-ast_type_traits::DynTypedNode
-createDynTypedNode(const NestedNameSpecifierLoc &Node) {
- return ast_type_traits::DynTypedNode::create(Node);
-}
-/// @}
-
-/// A \c RecursiveASTVisitor that builds a map from nodes to their
-/// parents as defined by the \c RecursiveASTVisitor.
-///
-/// Note that the relationship described here is purely in terms of AST
-/// traversal - there are other relationships (for example declaration context)
-/// in the AST that are better modeled by special matchers.
-///
-/// FIXME: Currently only builds up the map using \c Stmt and \c Decl nodes.
-class ASTContext::ParentMap::ASTVisitor
- : public RecursiveASTVisitor<ASTVisitor> {
-public:
- ASTVisitor(ParentMap &Map, ASTContext &Context)
- : Map(Map), Context(Context) {}
-
-private:
- friend class RecursiveASTVisitor<ASTVisitor>;
-
- using VisitorBase = RecursiveASTVisitor<ASTVisitor>;
-
- bool shouldVisitTemplateInstantiations() const { return true; }
-
- bool shouldVisitImplicitCode() const { return true; }
-
- template <typename T, typename MapNodeTy, typename BaseTraverseFn,
- typename MapTy>
- bool TraverseNode(T Node, MapNodeTy MapNode, BaseTraverseFn BaseTraverse,
- MapTy *Parents) {
- if (!Node)
- return true;
- if (ParentStack.size() > 0) {
- // FIXME: Currently we add the same parent multiple times, but only
- // when no memoization data is available for the type.
- // For example when we visit all subexpressions of template
- // instantiations; this is suboptimal, but benign: the only way to
- // visit those is with hasAncestor / hasParent, and those do not create
- // new matches.
- // The plan is to enable DynTypedNode to be storable in a map or hash
- // map. The main problem there is to implement hash functions /
- // comparison operators for all types that DynTypedNode supports that
- // do not have pointer identity.
- auto &NodeOrVector = (*Parents)[MapNode];
- if (NodeOrVector.isNull()) {
- if (const auto *D = ParentStack.back().get<Decl>())
- NodeOrVector = D;
- else if (const auto *S = ParentStack.back().get<Stmt>())
- NodeOrVector = S;
- else
- NodeOrVector = new ast_type_traits::DynTypedNode(ParentStack.back());
- } else {
- if (!NodeOrVector.template is<ParentVector *>()) {
- auto *Vector = new ParentVector(
- 1, getSingleDynTypedNodeFromParentMap(NodeOrVector));
- delete NodeOrVector
- .template dyn_cast<ast_type_traits::DynTypedNode *>();
- NodeOrVector = Vector;
- }
-
- auto *Vector = NodeOrVector.template get<ParentVector *>();
- // Skip duplicates for types that have memoization data.
- // We must check that the type has memoization data before calling
- // std::find() because DynTypedNode::operator== can't compare all
- // types.
- bool Found = ParentStack.back().getMemoizationData() &&
- std::find(Vector->begin(), Vector->end(),
- ParentStack.back()) != Vector->end();
- if (!Found)
- Vector->push_back(ParentStack.back());
- }
- }
- ParentStack.push_back(createDynTypedNode(Node));
- bool Result = BaseTraverse();
- ParentStack.pop_back();
- return Result;
- }
-
- bool TraverseDecl(Decl *DeclNode) {
- return TraverseNode(
- DeclNode, DeclNode, [&] { return VisitorBase::TraverseDecl(DeclNode); },
- &Map.PointerParents);
- }
-
- bool TraverseStmt(Stmt *StmtNode) {
- Stmt *FilteredNode = StmtNode;
- if (auto *ExprNode = dyn_cast_or_null<Expr>(FilteredNode))
- FilteredNode = Context.traverseIgnored(ExprNode);
- return TraverseNode(FilteredNode, FilteredNode,
- [&] { return VisitorBase::TraverseStmt(FilteredNode); },
- &Map.PointerParents);
- }
-
- bool TraverseTypeLoc(TypeLoc TypeLocNode) {
- return TraverseNode(
- TypeLocNode, ast_type_traits::DynTypedNode::create(TypeLocNode),
- [&] { return VisitorBase::TraverseTypeLoc(TypeLocNode); },
- &Map.OtherParents);
- }
-
- bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) {
- return TraverseNode(
- NNSLocNode, ast_type_traits::DynTypedNode::create(NNSLocNode),
- [&] { return VisitorBase::TraverseNestedNameSpecifierLoc(NNSLocNode); },
- &Map.OtherParents);
- }
-
- ParentMap &Map;
- ASTContext &Context;
- llvm::SmallVector<ast_type_traits::DynTypedNode, 16> ParentStack;
-};
-
-ASTContext::ParentMap::ParentMap(ASTContext &Ctx) {
- ASTVisitor(*this, Ctx).TraverseAST(Ctx);
-}
-
-ASTContext::DynTypedNodeList
-ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) {
- std::unique_ptr<ParentMap> &P = Parents[Traversal];
- if (!P)
- // We build the parent map for the traversal scope (usually whole TU), as
- // hasAncestor can escape any subtree.
- P = std::make_unique<ParentMap>(*this);
- return P->getParents(Node);
-}
-
bool
ASTContext::ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl,
const ObjCMethodDecl *MethodImpl) {
@@ -10958,3 +11151,16 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
Target->getTargetOpts().Features);
}
}
+
+OMPTraitInfo &ASTContext::getNewOMPTraitInfo() {
+ OMPTraitInfoVector.emplace_back(new OMPTraitInfo());
+ return *OMPTraitInfoVector.back();
+}
+
+const DiagnosticBuilder &
+clang::operator<<(const DiagnosticBuilder &DB,
+ const ASTContext::SectionInfo &Section) {
+ if (Section.Decl)
+ return DB << Section.Decl;
+ return DB << "a prior #pragma section";
+}
diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp
index ea4d0dea58a32..05adf226bae37 100644
--- a/clang/lib/AST/ASTDiagnostic.cpp
+++ b/clang/lib/AST/ASTDiagnostic.cpp
@@ -1715,8 +1715,9 @@ class TemplateDiff {
bool FromDefault, bool ToDefault, bool Same) {
assert((FromTD || ToTD) && "Only one template argument may be missing.");
- std::string FromName = FromTD ? FromTD->getName() : "(no argument)";
- std::string ToName = ToTD ? ToTD->getName() : "(no argument)";
+ std::string FromName =
+ std::string(FromTD ? FromTD->getName() : "(no argument)");
+ std::string ToName = std::string(ToTD ? ToTD->getName() : "(no argument)");
if (FromTD && ToTD && FromName == ToName) {
FromName = FromTD->getQualifiedNameAsString();
ToName = ToTD->getQualifiedNameAsString();
diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp
index 22196a1a26004..284e5bdbc6b0f 100644
--- a/clang/lib/AST/ASTDumper.cpp
+++ b/clang/lib/AST/ASTDumper.cpp
@@ -54,7 +54,7 @@ void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {
NodeDumper.AddChild([=] {
NodeDumper.dumpBareDeclRef(*RI);
- if ((*RI)->isHidden())
+ if (!(*RI)->isUnconditionallyVisible())
OS << " hidden";
// If requested, dump the redecl chain for this lookup.
@@ -159,17 +159,22 @@ void QualType::dump(const char *msg) const {
dump();
}
-LLVM_DUMP_METHOD void QualType::dump() const { dump(llvm::errs()); }
+LLVM_DUMP_METHOD void QualType::dump() const {
+ ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
+ Dumper.Visit(*this);
+}
-LLVM_DUMP_METHOD void QualType::dump(llvm::raw_ostream &OS) const {
- ASTDumper Dumper(OS, nullptr, nullptr);
+LLVM_DUMP_METHOD void QualType::dump(llvm::raw_ostream &OS,
+ const ASTContext &Context) const {
+ ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
Dumper.Visit(*this);
}
-LLVM_DUMP_METHOD void Type::dump() const { dump(llvm::errs()); }
+LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); }
-LLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS) const {
- QualType(this, 0).dump(OS);
+LLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS,
+ const ASTContext &Context) const {
+ QualType(this, 0).dump(OS, Context);
}
//===----------------------------------------------------------------------===//
@@ -189,8 +194,7 @@ LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS, bool Deserialize,
(void)Deserialize; // FIXME?
P.Visit(this);
} else {
- ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &SM,
- SM.getDiagnostics().getShowColors(), Ctx.getPrintingPolicy());
+ ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
P.setDeserialize(Deserialize);
P.Visit(this);
}
@@ -198,9 +202,7 @@ LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS, bool Deserialize,
LLVM_DUMP_METHOD void Decl::dumpColor() const {
const ASTContext &Ctx = getASTContext();
- ASTDumper P(llvm::errs(), &Ctx.getCommentCommandTraits(),
- &Ctx.getSourceManager(), /*ShowColors*/ true,
- Ctx.getPrintingPolicy());
+ ASTDumper P(llvm::errs(), Ctx, /*ShowColors=*/true);
P.Visit(this);
}
@@ -214,10 +216,8 @@ LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS,
const DeclContext *DC = this;
while (!DC->isTranslationUnit())
DC = DC->getParent();
- ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
- const SourceManager &SM = Ctx.getSourceManager();
- ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &Ctx.getSourceManager(),
- SM.getDiagnostics().getShowColors(), Ctx.getPrintingPolicy());
+ const ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
+ ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
P.setDeserialize(Deserialize);
P.dumpLookups(this, DumpDecls);
}
@@ -226,27 +226,19 @@ LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS,
// Stmt method implementations
//===----------------------------------------------------------------------===//
-LLVM_DUMP_METHOD void Stmt::dump(SourceManager &SM) const {
- dump(llvm::errs(), SM);
-}
-
-LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS, SourceManager &SM) const {
- ASTDumper P(OS, nullptr, &SM);
- P.Visit(this);
-}
-
-LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS) const {
- ASTDumper P(OS, nullptr, nullptr);
+LLVM_DUMP_METHOD void Stmt::dump() const {
+ ASTDumper P(llvm::errs(), /*ShowColors=*/false);
P.Visit(this);
}
-LLVM_DUMP_METHOD void Stmt::dump() const {
- ASTDumper P(llvm::errs(), nullptr, nullptr);
+LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS,
+ const ASTContext &Context) const {
+ ASTDumper P(OS, Context, Context.getDiagnostics().getShowColors());
P.Visit(this);
}
LLVM_DUMP_METHOD void Stmt::dumpColor() const {
- ASTDumper P(llvm::errs(), nullptr, nullptr, /*ShowColors*/true);
+ ASTDumper P(llvm::errs(), /*ShowColors=*/true);
P.Visit(this);
}
@@ -255,27 +247,42 @@ LLVM_DUMP_METHOD void Stmt::dumpColor() const {
//===----------------------------------------------------------------------===//
LLVM_DUMP_METHOD void Comment::dump() const {
- dump(llvm::errs(), nullptr, nullptr);
-}
-
-LLVM_DUMP_METHOD void Comment::dump(const ASTContext &Context) const {
- dump(llvm::errs(), &Context.getCommentCommandTraits(),
- &Context.getSourceManager());
+ const auto *FC = dyn_cast<FullComment>(this);
+ if (!FC)
+ return;
+ ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
+ Dumper.Visit(FC, FC);
}
-void Comment::dump(raw_ostream &OS, const CommandTraits *Traits,
- const SourceManager *SM) const {
- const FullComment *FC = dyn_cast<FullComment>(this);
+LLVM_DUMP_METHOD void Comment::dump(raw_ostream &OS,
+ const ASTContext &Context) const {
+ const auto *FC = dyn_cast<FullComment>(this);
if (!FC)
return;
- ASTDumper D(OS, Traits, SM);
- D.Visit(FC, FC);
+ ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
+ Dumper.Visit(FC, FC);
}
LLVM_DUMP_METHOD void Comment::dumpColor() const {
- const FullComment *FC = dyn_cast<FullComment>(this);
+ const auto *FC = dyn_cast<FullComment>(this);
if (!FC)
return;
- ASTDumper D(llvm::errs(), nullptr, nullptr, /*ShowColors*/true);
- D.Visit(FC, FC);
+ ASTDumper Dumper(llvm::errs(), /*ShowColors=*/true);
+ Dumper.Visit(FC, FC);
+}
+
+//===----------------------------------------------------------------------===//
+// APValue method implementations
+//===----------------------------------------------------------------------===//
+
+LLVM_DUMP_METHOD void APValue::dump() const {
+ ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
+ Dumper.Visit(*this, /*Ty=*/QualType());
+}
+
+LLVM_DUMP_METHOD void APValue::dump(raw_ostream &OS,
+ const ASTContext &Context) const {
+ ASTDumper Dumper(llvm::errs(), Context,
+ Context.getDiagnostics().getShowColors());
+ Dumper.Visit(*this, /*Ty=*/Context.getPointerType(Context.CharTy));
}
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 22fb67478c969..3779e0cb872b5 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -186,36 +186,25 @@ namespace clang {
return import(*From);
}
- template <class T>
- Expected<std::tuple<T>>
- importSeq(const T &From) {
- Expected<T> ToOrErr = import(From);
- if (!ToOrErr)
- return ToOrErr.takeError();
- return std::make_tuple<T>(std::move(*ToOrErr));
- }
-
- // Import multiple objects with a single function call.
- // This should work for every type for which a variant of `import` exists.
- // The arguments are processed from left to right and import is stopped on
- // first error.
- template <class THead, class... TTail>
- Expected<std::tuple<THead, TTail...>>
- importSeq(const THead &FromHead, const TTail &...FromTail) {
- Expected<std::tuple<THead>> ToHeadOrErr = importSeq(FromHead);
- if (!ToHeadOrErr)
- return ToHeadOrErr.takeError();
- Expected<std::tuple<TTail...>> ToTailOrErr = importSeq(FromTail...);
- if (!ToTailOrErr)
- return ToTailOrErr.takeError();
- return std::tuple_cat(*ToHeadOrErr, *ToTailOrErr);
+ // Helper for chaining together multiple imports. If an error is detected,
+ // subsequent imports will return default constructed nodes, so that failure
+ // can be detected with a single conditional branch after a sequence of
+ // imports.
+ template <typename T> T importChecked(Error &Err, const T &From) {
+ // Don't attempt to import nodes if we hit an error earlier.
+ if (Err)
+ return T{};
+ Expected<T> MaybeVal = import(From);
+ if (!MaybeVal) {
+ Err = MaybeVal.takeError();
+ return T{};
+ }
+ return *MaybeVal;
}
-// Wrapper for an overload set.
+ // Wrapper for an overload set.
template <typename ToDeclT> struct CallOverloadedCreateFun {
- template <typename... Args>
- auto operator()(Args &&... args)
- -> decltype(ToDeclT::Create(std::forward<Args>(args)...)) {
+ template <typename... Args> decltype(auto) operator()(Args &&... args) {
return ToDeclT::Create(std::forward<Args>(args)...);
}
};
@@ -474,7 +463,7 @@ namespace clang {
ParmVarDecl *ToParam);
template <typename T>
- bool hasSameVisibilityContext(T *Found, T *From);
+ bool hasSameVisibilityContextAndLinkage(T *Found, T *From);
bool IsStructuralMatch(Decl *From, Decl *To, bool Complain);
bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord,
@@ -599,6 +588,7 @@ namespace clang {
ExpectedStmt VisitIntegerLiteral(IntegerLiteral *E);
ExpectedStmt VisitFloatingLiteral(FloatingLiteral *E);
ExpectedStmt VisitImaginaryLiteral(ImaginaryLiteral *E);
+ ExpectedStmt VisitFixedPointLiteral(FixedPointLiteral *E);
ExpectedStmt VisitCharacterLiteral(CharacterLiteral *E);
ExpectedStmt VisitStringLiteral(StringLiteral *E);
ExpectedStmt VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
@@ -659,7 +649,7 @@ namespace clang {
template<typename IIter, typename OIter>
Error ImportArrayChecked(IIter Ibegin, IIter Iend, OIter Obegin) {
- using ItemT = typename std::remove_reference<decltype(*Obegin)>::type;
+ using ItemT = std::remove_reference_t<decltype(*Obegin)>;
for (; Ibegin != Iend; ++Ibegin, ++Obegin) {
Expected<ItemT> ToOrErr = import(*Ibegin);
if (!ToOrErr)
@@ -984,7 +974,10 @@ Expected<LambdaCapture> ASTNodeImporter::import(const LambdaCapture &From) {
}
template <typename T>
-bool ASTNodeImporter::hasSameVisibilityContext(T *Found, T *From) {
+bool ASTNodeImporter::hasSameVisibilityContextAndLinkage(T *Found, T *From) {
+ if (Found->getLinkageInternal() != From->getLinkageInternal())
+ return false;
+
if (From->hasExternalFormalLinkage())
return Found->hasExternalFormalLinkage();
if (Importer.GetFromTU(Found) != From->getTranslationUnitDecl())
@@ -997,8 +990,11 @@ bool ASTNodeImporter::hasSameVisibilityContext(T *Found, T *From) {
}
template <>
-bool ASTNodeImporter::hasSameVisibilityContext(TypedefNameDecl *Found,
+bool ASTNodeImporter::hasSameVisibilityContextAndLinkage(TypedefNameDecl *Found,
TypedefNameDecl *From) {
+ if (Found->getLinkageInternal() != From->getLinkageInternal())
+ return false;
+
if (From->isInAnonymousNamespace() && Found->isInAnonymousNamespace())
return Importer.GetFromTU(Found) == From->getTranslationUnitDecl();
return From->isInAnonymousNamespace() == Found->isInAnonymousNamespace();
@@ -1149,12 +1145,11 @@ ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) {
ExpectedType
ASTNodeImporter::VisitConstantArrayType(const ConstantArrayType *T) {
- QualType ToElementType;
- const Expr *ToSizeExpr;
- if (auto Imp = importSeq(T->getElementType(), T->getSizeExpr()))
- std::tie(ToElementType, ToSizeExpr) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto ToElementType = importChecked(Err, T->getElementType());
+ auto ToSizeExpr = importChecked(Err, T->getSizeExpr());
+ if (Err)
+ return std::move(Err);
return Importer.getToContext().getConstantArrayType(
ToElementType, T->getSize(), ToSizeExpr, T->getSizeModifier(),
@@ -1174,15 +1169,12 @@ ASTNodeImporter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
ExpectedType
ASTNodeImporter::VisitVariableArrayType(const VariableArrayType *T) {
- QualType ToElementType;
- Expr *ToSizeExpr;
- SourceRange ToBracketsRange;
- if (auto Imp = importSeq(
- T->getElementType(), T->getSizeExpr(), T->getBracketsRange()))
- std::tie(ToElementType, ToSizeExpr, ToBracketsRange) = *Imp;
- else
- return Imp.takeError();
-
+ Error Err = Error::success();
+ QualType ToElementType = importChecked(Err, T->getElementType());
+ Expr *ToSizeExpr = importChecked(Err, T->getSizeExpr());
+ SourceRange ToBracketsRange = importChecked(Err, T->getBracketsRange());
+ if (Err)
+ return std::move(Err);
return Importer.getToContext().getVariableArrayType(
ToElementType, ToSizeExpr, T->getSizeModifier(),
T->getIndexTypeCVRQualifiers(), ToBracketsRange);
@@ -1190,14 +1182,12 @@ ASTNodeImporter::VisitVariableArrayType(const VariableArrayType *T) {
ExpectedType ASTNodeImporter::VisitDependentSizedArrayType(
const DependentSizedArrayType *T) {
- QualType ToElementType;
- Expr *ToSizeExpr;
- SourceRange ToBracketsRange;
- if (auto Imp = importSeq(
- T->getElementType(), T->getSizeExpr(), T->getBracketsRange()))
- std::tie(ToElementType, ToSizeExpr, ToBracketsRange) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ QualType ToElementType = importChecked(Err, T->getElementType());
+ Expr *ToSizeExpr = importChecked(Err, T->getSizeExpr());
+ SourceRange ToBracketsRange = importChecked(Err, T->getBracketsRange());
+ if (Err)
+ return std::move(Err);
// SizeExpr may be null if size is not specified directly.
// For example, 'int a[]'.
@@ -1262,26 +1252,24 @@ ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) {
}
FunctionProtoType::ExtProtoInfo FromEPI = T->getExtProtoInfo();
+ Error Err = Error::success();
FunctionProtoType::ExtProtoInfo ToEPI;
-
- auto Imp = importSeq(
- FromEPI.ExceptionSpec.NoexceptExpr,
- FromEPI.ExceptionSpec.SourceDecl,
- FromEPI.ExceptionSpec.SourceTemplate);
- if (!Imp)
- return Imp.takeError();
-
ToEPI.ExtInfo = FromEPI.ExtInfo;
ToEPI.Variadic = FromEPI.Variadic;
ToEPI.HasTrailingReturn = FromEPI.HasTrailingReturn;
ToEPI.TypeQuals = FromEPI.TypeQuals;
ToEPI.RefQualifier = FromEPI.RefQualifier;
ToEPI.ExceptionSpec.Type = FromEPI.ExceptionSpec.Type;
+ ToEPI.ExceptionSpec.NoexceptExpr =
+ importChecked(Err, FromEPI.ExceptionSpec.NoexceptExpr);
+ ToEPI.ExceptionSpec.SourceDecl =
+ importChecked(Err, FromEPI.ExceptionSpec.SourceDecl);
+ ToEPI.ExceptionSpec.SourceTemplate =
+ importChecked(Err, FromEPI.ExceptionSpec.SourceTemplate);
ToEPI.ExceptionSpec.Exceptions = ExceptionTypes;
- std::tie(
- ToEPI.ExceptionSpec.NoexceptExpr,
- ToEPI.ExceptionSpec.SourceDecl,
- ToEPI.ExceptionSpec.SourceTemplate) = *Imp;
+
+ if (Err)
+ return std::move(Err);
return Importer.getToContext().getFunctionType(
*ToReturnTypeOrErr, ArgTypes, ToEPI);
@@ -1289,12 +1277,11 @@ ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) {
ExpectedType ASTNodeImporter::VisitUnresolvedUsingType(
const UnresolvedUsingType *T) {
- UnresolvedUsingTypenameDecl *ToD;
- Decl *ToPrevD;
- if (auto Imp = importSeq(T->getDecl(), T->getDecl()->getPreviousDecl()))
- std::tie(ToD, ToPrevD) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto ToD = importChecked(Err, T->getDecl());
+ auto ToPrevD = importChecked(Err, T->getDecl()->getPreviousDecl());
+ if (Err)
+ return std::move(Err);
return Importer.getToContext().getTypeDeclType(
ToD, cast_or_null<TypeDecl>(ToPrevD));
@@ -1366,9 +1353,21 @@ ExpectedType ASTNodeImporter::VisitAutoType(const AutoType *T) {
if (!ToDeducedTypeOrErr)
return ToDeducedTypeOrErr.takeError();
- return Importer.getToContext().getAutoType(*ToDeducedTypeOrErr,
- T->getKeyword(),
- /*IsDependent*/false);
+ ExpectedDecl ToTypeConstraintConcept = import(T->getTypeConstraintConcept());
+ if (!ToTypeConstraintConcept)
+ return ToTypeConstraintConcept.takeError();
+
+ SmallVector<TemplateArgument, 2> ToTemplateArgs;
+ ArrayRef<TemplateArgument> FromTemplateArgs = T->getTypeConstraintArguments();
+ if (Error Err = ImportTemplateArguments(FromTemplateArgs.data(),
+ FromTemplateArgs.size(),
+ ToTemplateArgs))
+ return std::move(Err);
+
+ return Importer.getToContext().getAutoType(
+ *ToDeducedTypeOrErr, T->getKeyword(), /*IsDependent*/false,
+ /*IsPack=*/false, cast_or_null<ConceptDecl>(*ToTypeConstraintConcept),
+ ToTemplateArgs);
}
ExpectedType ASTNodeImporter::VisitInjectedClassNameType(
@@ -1741,7 +1740,7 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
// fix since operations such as code generation will expect this to be so.
if (ImportedOrErr) {
FieldDecl *FieldFrom = dyn_cast_or_null<FieldDecl>(From);
- Decl *ImportedDecl = (Decl*)*ImportedOrErr;
+ Decl *ImportedDecl = *ImportedOrErr;
FieldDecl *FieldTo = dyn_cast_or_null<FieldDecl>(ImportedDecl);
if (FieldFrom && FieldTo) {
const RecordType *RecordFrom = FieldFrom->getType()->getAs<RecordType>();
@@ -1891,6 +1890,19 @@ Error ASTNodeImporter::ImportDefinition(
// set in CXXRecordDecl::CreateLambda. We must import the contained
// decls here and finish the definition.
(To->isLambda() && shouldForceImportDeclContext(Kind))) {
+ if (To->isLambda()) {
+ auto *FromCXXRD = cast<CXXRecordDecl>(From);
+ SmallVector<LambdaCapture, 8> ToCaptures;
+ ToCaptures.reserve(FromCXXRD->capture_size());
+ for (const auto &FromCapture : FromCXXRD->captures()) {
+ if (auto ToCaptureOrErr = import(FromCapture))
+ ToCaptures.push_back(*ToCaptureOrErr);
+ else
+ return ToCaptureOrErr.takeError();
+ }
+ cast<CXXRecordDecl>(To)->setCaptures(ToCaptures);
+ }
+
Error Result = ImportDeclContext(From, /*ForceImport=*/true);
// Finish the definition of the lambda, set isBeingDefined to false.
if (To->isLambda())
@@ -2236,14 +2248,13 @@ ExpectedDecl ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) {
DeclContext *DC = *DCOrErr;
DeclContext *LexicalDC = DC;
- SourceLocation ToLocation, ToRParenLoc;
- Expr *ToAssertExpr;
- StringLiteral *ToMessage;
- if (auto Imp = importSeq(
- D->getLocation(), D->getAssertExpr(), D->getMessage(), D->getRParenLoc()))
- std::tie(ToLocation, ToAssertExpr, ToMessage, ToRParenLoc) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto ToLocation = importChecked(Err, D->getLocation());
+ auto ToRParenLoc = importChecked(Err, D->getRParenLoc());
+ auto ToAssertExpr = importChecked(Err, D->getAssertExpr());
+ auto ToMessage = importChecked(Err, D->getMessage());
+ if (Err)
+ return std::move(Err);
StaticAssertDecl *ToD;
if (GetImportedOrCreateDecl(
@@ -2352,17 +2363,15 @@ ExpectedDecl ASTNodeImporter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
// NOTE: No conflict resolution is done for namespace aliases now.
- SourceLocation ToNamespaceLoc, ToAliasLoc, ToTargetNameLoc;
- NestedNameSpecifierLoc ToQualifierLoc;
- NamespaceDecl *ToNamespace;
- if (auto Imp = importSeq(
- D->getNamespaceLoc(), D->getAliasLoc(), D->getQualifierLoc(),
- D->getTargetNameLoc(), D->getNamespace()))
- std::tie(
- ToNamespaceLoc, ToAliasLoc, ToQualifierLoc, ToTargetNameLoc,
- ToNamespace) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto ToNamespaceLoc = importChecked(Err, D->getNamespaceLoc());
+ auto ToAliasLoc = importChecked(Err, D->getAliasLoc());
+ auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc());
+ auto ToTargetNameLoc = importChecked(Err, D->getTargetNameLoc());
+ auto ToNamespace = importChecked(Err, D->getNamespace());
+ if (Err)
+ return std::move(Err);
+
IdentifierInfo *ToIdentifier = Importer.Import(D->getIdentifier());
NamespaceAliasDecl *ToD;
@@ -2403,7 +2412,7 @@ ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) {
if (!FoundDecl->isInIdentifierNamespace(IDNS))
continue;
if (auto *FoundTypedef = dyn_cast<TypedefNameDecl>(FoundDecl)) {
- if (!hasSameVisibilityContext(FoundTypedef, D))
+ if (!hasSameVisibilityContextAndLinkage(FoundTypedef, D))
continue;
QualType FromUT = D->getUnderlyingType();
@@ -2431,17 +2440,16 @@ ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) {
}
}
- QualType ToUnderlyingType;
- TypeSourceInfo *ToTypeSourceInfo;
- SourceLocation ToBeginLoc;
- if (auto Imp = importSeq(
- D->getUnderlyingType(), D->getTypeSourceInfo(), D->getBeginLoc()))
- std::tie(ToUnderlyingType, ToTypeSourceInfo, ToBeginLoc) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto ToUnderlyingType = importChecked(Err, D->getUnderlyingType());
+ auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo());
+ auto ToBeginLoc = importChecked(Err, D->getBeginLoc());
+ if (Err)
+ return std::move(Err);
// Create the new typedef node.
// FIXME: ToUnderlyingType is not used.
+ (void)ToUnderlyingType;
TypedefNameDecl *ToTypedef;
if (IsAlias) {
if (GetImportedOrCreateDecl<TypeAliasDecl>(
@@ -2509,12 +2517,11 @@ ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
}
}
- TemplateParameterList *ToTemplateParameters;
- TypeAliasDecl *ToTemplatedDecl;
- if (auto Imp = importSeq(D->getTemplateParameters(), D->getTemplatedDecl()))
- std::tie(ToTemplateParameters, ToTemplatedDecl) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto ToTemplateParameters = importChecked(Err, D->getTemplateParameters());
+ auto ToTemplatedDecl = importChecked(Err, D->getTemplatedDecl());
+ if (Err)
+ return std::move(Err);
TypeAliasTemplateDecl *ToAlias;
if (GetImportedOrCreateDecl(ToAlias, D, Importer.getToContext(), DC, Loc,
@@ -2591,6 +2598,7 @@ ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
IDNS |= Decl::IDNS_Ordinary;
// We may already have an enum of the same name; try to find and match it.
+ EnumDecl *PrevDecl = nullptr;
if (!DC->isFunctionOrMethod() && SearchName) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
auto FoundDecls =
@@ -2605,10 +2613,15 @@ ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
}
if (auto *FoundEnum = dyn_cast<EnumDecl>(FoundDecl)) {
- if (!hasSameVisibilityContext(FoundEnum, D))
+ if (!hasSameVisibilityContextAndLinkage(FoundEnum, D))
continue;
- if (IsStructuralMatch(D, FoundEnum))
- return Importer.MapImported(D, FoundEnum);
+ if (IsStructuralMatch(D, FoundEnum)) {
+ EnumDecl *FoundDef = FoundEnum->getDefinition();
+ if (D->isThisDeclarationADefinition() && FoundDef)
+ return Importer.MapImported(D, FoundDef);
+ PrevDecl = FoundEnum->getMostRecentDecl();
+ break;
+ }
ConflictingDecls.push_back(FoundDecl);
}
}
@@ -2624,21 +2637,19 @@ ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
}
}
- SourceLocation ToBeginLoc;
- NestedNameSpecifierLoc ToQualifierLoc;
- QualType ToIntegerType;
- SourceRange ToBraceRange;
- if (auto Imp = importSeq(D->getBeginLoc(), D->getQualifierLoc(),
- D->getIntegerType(), D->getBraceRange()))
- std::tie(ToBeginLoc, ToQualifierLoc, ToIntegerType, ToBraceRange) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto ToBeginLoc = importChecked(Err, D->getBeginLoc());
+ auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc());
+ auto ToIntegerType = importChecked(Err, D->getIntegerType());
+ auto ToBraceRange = importChecked(Err, D->getBraceRange());
+ if (Err)
+ return std::move(Err);
// Create the enum declaration.
EnumDecl *D2;
if (GetImportedOrCreateDecl(
D2, D, Importer.getToContext(), DC, ToBeginLoc,
- Loc, Name.getAsIdentifierInfo(), nullptr, D->isScoped(),
+ Loc, Name.getAsIdentifierInfo(), PrevDecl, D->isScoped(),
D->isScopedUsingClassTag(), D->isFixed()))
return D2;
@@ -2724,7 +2735,7 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
if (!IsStructuralMatch(D, FoundRecord, false))
continue;
- if (!hasSameVisibilityContext(FoundRecord, D))
+ if (!hasSameVisibilityContextAndLinkage(FoundRecord, D))
continue;
if (IsStructuralMatch(D, FoundRecord)) {
@@ -2784,7 +2795,7 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
return CDeclOrErr.takeError();
D2CXX->setLambdaMangling(DCXX->getLambdaManglingNumber(), *CDeclOrErr,
DCXX->hasKnownLambdaInternalLinkage());
- } else if (DCXX->isInjectedClassName()) {
+ } else if (DCXX->isInjectedClassName()) {
// We have to be careful to do a similar dance to the one in
// Sema::ActOnStartCXXMemberDeclarations
const bool DelayTypeCreation = true;
@@ -3172,7 +3183,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
continue;
if (auto *FoundFunction = dyn_cast<FunctionDecl>(FoundDecl)) {
- if (!hasSameVisibilityContext(FoundFunction, D))
+ if (!hasSameVisibilityContextAndLinkage(FoundFunction, D))
continue;
if (IsStructuralMatch(D, FoundFunction)) {
@@ -3275,18 +3286,16 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
FromReturnTy, FromFPT->getParamTypes(), FromEPI);
}
- QualType T;
- TypeSourceInfo *TInfo;
- SourceLocation ToInnerLocStart, ToEndLoc;
- NestedNameSpecifierLoc ToQualifierLoc;
- Expr *TrailingRequiresClause;
- if (auto Imp = importSeq(
- FromTy, D->getTypeSourceInfo(), D->getInnerLocStart(),
- D->getQualifierLoc(), D->getEndLoc(), D->getTrailingRequiresClause()))
- std::tie(T, TInfo, ToInnerLocStart, ToQualifierLoc, ToEndLoc,
- TrailingRequiresClause) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto T = importChecked(Err, FromTy);
+ auto TInfo = importChecked(Err, D->getTypeSourceInfo());
+ auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart());
+ auto ToEndLoc = importChecked(Err, D->getEndLoc());
+ auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc());
+ auto TrailingRequiresClause =
+ importChecked(Err, D->getTrailingRequiresClause());
+ if (Err)
+ return std::move(Err);
// Import the function parameters.
SmallVector<ParmVarDecl *, 8> Parameters;
@@ -3302,10 +3311,10 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
if (auto *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) {
Expr *ExplicitExpr = nullptr;
if (FromConstructor->getExplicitSpecifier().getExpr()) {
- auto Imp = importSeq(FromConstructor->getExplicitSpecifier().getExpr());
+ auto Imp = import(FromConstructor->getExplicitSpecifier().getExpr());
if (!Imp)
return Imp.takeError();
- std::tie(ExplicitExpr) = *Imp;
+ ExplicitExpr = *Imp;
}
if (GetImportedOrCreateDecl<CXXConstructorDecl>(
ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
@@ -3320,16 +3329,12 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
return ToFunction;
} else if (CXXDestructorDecl *FromDtor = dyn_cast<CXXDestructorDecl>(D)) {
- auto Imp =
- importSeq(const_cast<FunctionDecl *>(FromDtor->getOperatorDelete()),
- FromDtor->getOperatorDeleteThisArg());
-
- if (!Imp)
- return Imp.takeError();
-
- FunctionDecl *ToOperatorDelete;
- Expr *ToThisArg;
- std::tie(ToOperatorDelete, ToThisArg) = *Imp;
+ Error Err = Error::success();
+ auto ToOperatorDelete = importChecked(
+ Err, const_cast<FunctionDecl *>(FromDtor->getOperatorDelete()));
+ auto ToThisArg = importChecked(Err, FromDtor->getOperatorDeleteThisArg());
+ if (Err)
+ return std::move(Err);
if (GetImportedOrCreateDecl<CXXDestructorDecl>(
ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
@@ -3344,10 +3349,10 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
dyn_cast<CXXConversionDecl>(D)) {
Expr *ExplicitExpr = nullptr;
if (FromConversion->getExplicitSpecifier().getExpr()) {
- auto Imp = importSeq(FromConversion->getExplicitSpecifier().getExpr());
+ auto Imp = import(FromConversion->getExplicitSpecifier().getExpr());
if (!Imp)
return Imp.takeError();
- std::tie(ExplicitExpr) = *Imp;
+ ExplicitExpr = *Imp;
}
if (GetImportedOrCreateDecl<CXXConversionDecl>(
ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
@@ -3546,18 +3551,14 @@ ExpectedDecl ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
}
}
- QualType ToType;
- TypeSourceInfo *ToTInfo;
- Expr *ToBitWidth;
- SourceLocation ToInnerLocStart;
- Expr *ToInitializer;
- if (auto Imp = importSeq(
- D->getType(), D->getTypeSourceInfo(), D->getBitWidth(),
- D->getInnerLocStart(), D->getInClassInitializer()))
- std::tie(
- ToType, ToTInfo, ToBitWidth, ToInnerLocStart, ToInitializer) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto ToType = importChecked(Err, D->getType());
+ auto ToTInfo = importChecked(Err, D->getTypeSourceInfo());
+ auto ToBitWidth = importChecked(Err, D->getBitWidth());
+ auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart());
+ auto ToInitializer = importChecked(Err, D->getInClassInitializer());
+ if (Err)
+ return std::move(Err);
FieldDecl *ToField;
if (GetImportedOrCreateDecl(ToField, D, Importer.getToContext(), DC,
@@ -3645,6 +3646,54 @@ ExpectedDecl ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
return ToIndirectField;
}
+/// Used as return type of getFriendCountAndPosition.
+struct FriendCountAndPosition {
+ /// Number of similar looking friends.
+ unsigned int TotalCount;
+ /// Index of the specific FriendDecl.
+ unsigned int IndexOfDecl;
+};
+
+template <class T>
+static FriendCountAndPosition getFriendCountAndPosition(
+ const FriendDecl *FD,
+ llvm::function_ref<T(const FriendDecl *)> GetCanTypeOrDecl) {
+ unsigned int FriendCount = 0;
+ llvm::Optional<unsigned int> FriendPosition;
+ const auto *RD = cast<CXXRecordDecl>(FD->getLexicalDeclContext());
+
+ T TypeOrDecl = GetCanTypeOrDecl(FD);
+
+ for (const FriendDecl *FoundFriend : RD->friends()) {
+ if (FoundFriend == FD) {
+ FriendPosition = FriendCount;
+ ++FriendCount;
+ } else if (!FoundFriend->getFriendDecl() == !FD->getFriendDecl() &&
+ GetCanTypeOrDecl(FoundFriend) == TypeOrDecl) {
+ ++FriendCount;
+ }
+ }
+
+ assert(FriendPosition && "Friend decl not found in own parent.");
+
+ return {FriendCount, *FriendPosition};
+}
+
+static FriendCountAndPosition getFriendCountAndPosition(const FriendDecl *FD) {
+ if (FD->getFriendType())
+ return getFriendCountAndPosition<QualType>(FD, [](const FriendDecl *F) {
+ if (TypeSourceInfo *TSI = F->getFriendType())
+ return TSI->getType().getCanonicalType();
+ llvm_unreachable("Wrong friend object type.");
+ });
+ else
+ return getFriendCountAndPosition<Decl *>(FD, [](const FriendDecl *F) {
+ if (Decl *D = F->getFriendDecl())
+ return D->getCanonicalDecl();
+ llvm_unreachable("Wrong friend object type.");
+ });
+}
+
ExpectedDecl ASTNodeImporter::VisitFriendDecl(FriendDecl *D) {
// Import the major distinguishing characteristics of a declaration.
DeclContext *DC, *LexicalDC;
@@ -3653,25 +3702,37 @@ ExpectedDecl ASTNodeImporter::VisitFriendDecl(FriendDecl *D) {
// Determine whether we've already imported this decl.
// FriendDecl is not a NamedDecl so we cannot use lookup.
- auto *RD = cast<CXXRecordDecl>(DC);
+ // We try to maintain order and count of redundant friend declarations.
+ const auto *RD = cast<CXXRecordDecl>(DC);
FriendDecl *ImportedFriend = RD->getFirstFriend();
+ SmallVector<FriendDecl *, 2> ImportedEquivalentFriends;
while (ImportedFriend) {
+ bool Match = false;
if (D->getFriendDecl() && ImportedFriend->getFriendDecl()) {
- if (IsStructuralMatch(D->getFriendDecl(), ImportedFriend->getFriendDecl(),
- /*Complain=*/false))
- return Importer.MapImported(D, ImportedFriend);
-
+ Match =
+ IsStructuralMatch(D->getFriendDecl(), ImportedFriend->getFriendDecl(),
+ /*Complain=*/false);
} else if (D->getFriendType() && ImportedFriend->getFriendType()) {
- if (Importer.IsStructurallyEquivalent(
- D->getFriendType()->getType(),
- ImportedFriend->getFriendType()->getType(), true))
- return Importer.MapImported(D, ImportedFriend);
+ Match = Importer.IsStructurallyEquivalent(
+ D->getFriendType()->getType(),
+ ImportedFriend->getFriendType()->getType(), /*Complain=*/false);
}
+ if (Match)
+ ImportedEquivalentFriends.push_back(ImportedFriend);
+
ImportedFriend = ImportedFriend->getNextFriend();
}
+ FriendCountAndPosition CountAndPosition = getFriendCountAndPosition(D);
+
+ assert(ImportedEquivalentFriends.size() <= CountAndPosition.TotalCount &&
+ "Class with non-matching friends is imported, ODR check wrong?");
+ if (ImportedEquivalentFriends.size() == CountAndPosition.TotalCount)
+ return Importer.MapImported(
+ D, ImportedEquivalentFriends[CountAndPosition.IndexOfDecl]);
// Not found. Create it.
+ // The declarations will be put into order later by ImportDeclContext.
FriendDecl::FriendUnion ToFU;
if (NamedDecl *FriendD = D->getFriendDecl()) {
NamedDecl *ToFriendD;
@@ -3748,15 +3809,13 @@ ExpectedDecl ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
}
}
- QualType ToType;
- TypeSourceInfo *ToTypeSourceInfo;
- Expr *ToBitWidth;
- SourceLocation ToInnerLocStart;
- if (auto Imp = importSeq(
- D->getType(), D->getTypeSourceInfo(), D->getBitWidth(), D->getInnerLocStart()))
- std::tie(ToType, ToTypeSourceInfo, ToBitWidth, ToInnerLocStart) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto ToType = importChecked(Err, D->getType());
+ auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo());
+ auto ToBitWidth = importChecked(Err, D->getBitWidth());
+ auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart());
+ if (Err)
+ return std::move(Err);
ObjCIvarDecl *ToIvar;
if (GetImportedOrCreateDecl(
@@ -3806,7 +3865,7 @@ ExpectedDecl ASTNodeImporter::VisitVarDecl(VarDecl *D) {
continue;
if (auto *FoundVar = dyn_cast<VarDecl>(FoundDecl)) {
- if (!hasSameVisibilityContext(FoundVar, D))
+ if (!hasSameVisibilityContextAndLinkage(FoundVar, D))
continue;
if (Importer.IsStructurallyEquivalent(D->getType(),
FoundVar->getType())) {
@@ -3870,16 +3929,13 @@ ExpectedDecl ASTNodeImporter::VisitVarDecl(VarDecl *D) {
}
}
- QualType ToType;
- TypeSourceInfo *ToTypeSourceInfo;
- SourceLocation ToInnerLocStart;
- NestedNameSpecifierLoc ToQualifierLoc;
- if (auto Imp = importSeq(
- D->getType(), D->getTypeSourceInfo(), D->getInnerLocStart(),
- D->getQualifierLoc()))
- std::tie(ToType, ToTypeSourceInfo, ToInnerLocStart, ToQualifierLoc) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto ToType = importChecked(Err, D->getType());
+ auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo());
+ auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart());
+ auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc());
+ if (Err)
+ return std::move(Err);
// Create the imported variable.
VarDecl *ToVar;
@@ -3899,6 +3955,13 @@ ExpectedDecl ASTNodeImporter::VisitVarDecl(VarDecl *D) {
ToVar->setPreviousDecl(Recent);
}
+ // Import the described template, if any.
+ if (D->getDescribedVarTemplate()) {
+ auto ToVTOrErr = import(D->getDescribedVarTemplate());
+ if (!ToVTOrErr)
+ return ToVTOrErr.takeError();
+ }
+
if (Error Err = ImportInitializer(D, ToVar))
return std::move(Err);
@@ -3922,13 +3985,12 @@ ExpectedDecl ASTNodeImporter::VisitImplicitParamDecl(ImplicitParamDecl *D) {
// into the function declaration's context afterward.
DeclContext *DC = Importer.getToContext().getTranslationUnitDecl();
- DeclarationName ToDeclName;
- SourceLocation ToLocation;
- QualType ToType;
- if (auto Imp = importSeq(D->getDeclName(), D->getLocation(), D->getType()))
- std::tie(ToDeclName, ToLocation, ToType) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto ToDeclName = importChecked(Err, D->getDeclName());
+ auto ToLocation = importChecked(Err, D->getLocation());
+ auto ToType = importChecked(Err, D->getType());
+ if (Err)
+ return std::move(Err);
// Create the imported parameter.
ImplicitParamDecl *ToParm = nullptr;
@@ -3966,18 +4028,14 @@ ExpectedDecl ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) {
// into the function declaration's context afterward.
DeclContext *DC = Importer.getToContext().getTranslationUnitDecl();
- DeclarationName ToDeclName;
- SourceLocation ToLocation, ToInnerLocStart;
- QualType ToType;
- TypeSourceInfo *ToTypeSourceInfo;
- if (auto Imp = importSeq(
- D->getDeclName(), D->getLocation(), D->getType(), D->getInnerLocStart(),
- D->getTypeSourceInfo()))
- std::tie(
- ToDeclName, ToLocation, ToType, ToInnerLocStart,
- ToTypeSourceInfo) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto ToDeclName = importChecked(Err, D->getDeclName());
+ auto ToLocation = importChecked(Err, D->getLocation());
+ auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart());
+ auto ToType = importChecked(Err, D->getType());
+ auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo());
+ if (Err)
+ return std::move(Err);
ParmVarDecl *ToParm;
if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC,
@@ -4080,14 +4138,13 @@ ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
}
}
- SourceLocation ToEndLoc;
- QualType ToReturnType;
- TypeSourceInfo *ToReturnTypeSourceInfo;
- if (auto Imp = importSeq(
- D->getEndLoc(), D->getReturnType(), D->getReturnTypeSourceInfo()))
- std::tie(ToEndLoc, ToReturnType, ToReturnTypeSourceInfo) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto ToEndLoc = importChecked(Err, D->getEndLoc());
+ auto ToReturnType = importChecked(Err, D->getReturnType());
+ auto ToReturnTypeSourceInfo =
+ importChecked(Err, D->getReturnTypeSourceInfo());
+ if (Err)
+ return std::move(Err);
ObjCMethodDecl *ToMethod;
if (GetImportedOrCreateDecl(
@@ -4148,14 +4205,13 @@ ExpectedDecl ASTNodeImporter::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) {
if (ToD)
return ToD;
- SourceLocation ToVarianceLoc, ToLocation, ToColonLoc;
- TypeSourceInfo *ToTypeSourceInfo;
- if (auto Imp = importSeq(
- D->getVarianceLoc(), D->getLocation(), D->getColonLoc(),
- D->getTypeSourceInfo()))
- std::tie(ToVarianceLoc, ToLocation, ToColonLoc, ToTypeSourceInfo) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto ToVarianceLoc = importChecked(Err, D->getVarianceLoc());
+ auto ToLocation = importChecked(Err, D->getLocation());
+ auto ToColonLoc = importChecked(Err, D->getColonLoc());
+ auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo());
+ if (Err)
+ return std::move(Err);
ObjCTypeParamDecl *Result;
if (GetImportedOrCreateDecl(
@@ -4189,16 +4245,14 @@ ExpectedDecl ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
= ToInterface->FindCategoryDeclaration(Name.getAsIdentifierInfo());
ObjCCategoryDecl *ToCategory = MergeWithCategory;
if (!ToCategory) {
- SourceLocation ToAtStartLoc, ToCategoryNameLoc;
- SourceLocation ToIvarLBraceLoc, ToIvarRBraceLoc;
- if (auto Imp = importSeq(
- D->getAtStartLoc(), D->getCategoryNameLoc(),
- D->getIvarLBraceLoc(), D->getIvarRBraceLoc()))
- std::tie(
- ToAtStartLoc, ToCategoryNameLoc,
- ToIvarLBraceLoc, ToIvarRBraceLoc) = *Imp;
- else
- return Imp.takeError();
+
+ Error Err = Error::success();
+ auto ToAtStartLoc = importChecked(Err, D->getAtStartLoc());
+ auto ToCategoryNameLoc = importChecked(Err, D->getCategoryNameLoc());
+ auto ToIvarLBraceLoc = importChecked(Err, D->getIvarLBraceLoc());
+ auto ToIvarRBraceLoc = importChecked(Err, D->getIvarRBraceLoc());
+ if (Err)
+ return std::move(Err);
if (GetImportedOrCreateDecl(ToCategory, D, Importer.getToContext(), DC,
ToAtStartLoc, Loc,
@@ -4407,13 +4461,12 @@ ExpectedDecl ASTNodeImporter::VisitUsingDecl(UsingDecl *D) {
if (ToD)
return ToD;
- SourceLocation ToLoc, ToUsingLoc;
- NestedNameSpecifierLoc ToQualifierLoc;
- if (auto Imp = importSeq(
- D->getNameInfo().getLoc(), D->getUsingLoc(), D->getQualifierLoc()))
- std::tie(ToLoc, ToUsingLoc, ToQualifierLoc) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto ToLoc = importChecked(Err, D->getNameInfo().getLoc());
+ auto ToUsingLoc = importChecked(Err, D->getUsingLoc());
+ auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc());
+ if (Err)
+ return std::move(Err);
DeclarationNameInfo NameInfo(Name, ToLoc);
if (Error Err = ImportDeclarationNameLoc(D->getNameInfo(), NameInfo))
@@ -4504,18 +4557,15 @@ ExpectedDecl ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
if (!ToComAncestorOrErr)
return ToComAncestorOrErr.takeError();
- NamespaceDecl *ToNominatedNamespace;
- SourceLocation ToUsingLoc, ToNamespaceKeyLocation, ToIdentLocation;
- NestedNameSpecifierLoc ToQualifierLoc;
- if (auto Imp = importSeq(
- D->getNominatedNamespace(), D->getUsingLoc(),
- D->getNamespaceKeyLocation(), D->getQualifierLoc(),
- D->getIdentLocation()))
- std::tie(
- ToNominatedNamespace, ToUsingLoc, ToNamespaceKeyLocation,
- ToQualifierLoc, ToIdentLocation) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto ToNominatedNamespace = importChecked(Err, D->getNominatedNamespace());
+ auto ToUsingLoc = importChecked(Err, D->getUsingLoc());
+ auto ToNamespaceKeyLocation =
+ importChecked(Err, D->getNamespaceKeyLocation());
+ auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc());
+ auto ToIdentLocation = importChecked(Err, D->getIdentLocation());
+ if (Err)
+ return std::move(Err);
UsingDirectiveDecl *ToUsingDir;
if (GetImportedOrCreateDecl(ToUsingDir, D, Importer.getToContext(), DC,
@@ -4543,14 +4593,13 @@ ExpectedDecl ASTNodeImporter::VisitUnresolvedUsingValueDecl(
if (ToD)
return ToD;
- SourceLocation ToLoc, ToUsingLoc, ToEllipsisLoc;
- NestedNameSpecifierLoc ToQualifierLoc;
- if (auto Imp = importSeq(
- D->getNameInfo().getLoc(), D->getUsingLoc(), D->getQualifierLoc(),
- D->getEllipsisLoc()))
- std::tie(ToLoc, ToUsingLoc, ToQualifierLoc, ToEllipsisLoc) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto ToLoc = importChecked(Err, D->getNameInfo().getLoc());
+ auto ToUsingLoc = importChecked(Err, D->getUsingLoc());
+ auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc());
+ auto ToEllipsisLoc = importChecked(Err, D->getEllipsisLoc());
+ if (Err)
+ return std::move(Err);
DeclarationNameInfo NameInfo(Name, ToLoc);
if (Error Err = ImportDeclarationNameLoc(D->getNameInfo(), NameInfo))
@@ -4580,14 +4629,13 @@ ExpectedDecl ASTNodeImporter::VisitUnresolvedUsingTypenameDecl(
if (ToD)
return ToD;
- SourceLocation ToUsingLoc, ToTypenameLoc, ToEllipsisLoc;
- NestedNameSpecifierLoc ToQualifierLoc;
- if (auto Imp = importSeq(
- D->getUsingLoc(), D->getTypenameLoc(), D->getQualifierLoc(),
- D->getEllipsisLoc()))
- std::tie(ToUsingLoc, ToTypenameLoc, ToQualifierLoc, ToEllipsisLoc) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto ToUsingLoc = importChecked(Err, D->getUsingLoc());
+ auto ToTypenameLoc = importChecked(Err, D->getTypenameLoc());
+ auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc());
+ auto ToEllipsisLoc = importChecked(Err, D->getEllipsisLoc());
+ if (Err)
+ return std::move(Err);
UnresolvedUsingTypenameDecl *ToUsing;
if (GetImportedOrCreateDecl(ToUsing, D, Importer.getToContext(), DC,
@@ -4822,12 +4870,12 @@ ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
if (Error Err = ImportDeclContext(D, DC, LexicalDC))
return std::move(Err);
- SourceLocation ToLocation, ToAtStartLoc, ToCategoryNameLoc;
- if (auto Imp = importSeq(
- D->getLocation(), D->getAtStartLoc(), D->getCategoryNameLoc()))
- std::tie(ToLocation, ToAtStartLoc, ToCategoryNameLoc) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto ToLocation = importChecked(Err, D->getLocation());
+ auto ToAtStartLoc = importChecked(Err, D->getAtStartLoc());
+ auto ToCategoryNameLoc = importChecked(Err, D->getCategoryNameLoc());
+ if (Err)
+ return std::move(Err);
if (GetImportedOrCreateDecl(
ToImpl, D, Importer.getToContext(), DC,
@@ -4867,16 +4915,14 @@ ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
if (Error Err = ImportDeclContext(D, DC, LexicalDC))
return std::move(Err);
- SourceLocation ToLocation, ToAtStartLoc, ToSuperClassLoc;
- SourceLocation ToIvarLBraceLoc, ToIvarRBraceLoc;
- if (auto Imp = importSeq(
- D->getLocation(), D->getAtStartLoc(), D->getSuperClassLoc(),
- D->getIvarLBraceLoc(), D->getIvarRBraceLoc()))
- std::tie(
- ToLocation, ToAtStartLoc, ToSuperClassLoc,
- ToIvarLBraceLoc, ToIvarRBraceLoc) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto ToLocation = importChecked(Err, D->getLocation());
+ auto ToAtStartLoc = importChecked(Err, D->getAtStartLoc());
+ auto ToSuperClassLoc = importChecked(Err, D->getSuperClassLoc());
+ auto ToIvarLBraceLoc = importChecked(Err, D->getIvarLBraceLoc());
+ auto ToIvarRBraceLoc = importChecked(Err, D->getIvarRBraceLoc());
+ if (Err)
+ return std::move(Err);
if (GetImportedOrCreateDecl(Impl, D, Importer.getToContext(),
DC, Iface, Super,
@@ -4966,14 +5012,13 @@ ExpectedDecl ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
}
}
- QualType ToType;
- TypeSourceInfo *ToTypeSourceInfo;
- SourceLocation ToAtLoc, ToLParenLoc;
- if (auto Imp = importSeq(
- D->getType(), D->getTypeSourceInfo(), D->getAtLoc(), D->getLParenLoc()))
- std::tie(ToType, ToTypeSourceInfo, ToAtLoc, ToLParenLoc) = *Imp;
- else
- return Imp.takeError();
+ Error Err = Error::success();
+ auto ToType = importChecked(Err, D->getType());
+ auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo());
+ auto ToAtLoc = importChecked(Err, D->getAtLoc());
+ auto ToLParenLoc = importChecked(Err, D->getLParenLoc());
+ if (Err)
+ return std::move(Err);
// Create the new property.
ObjCPropertyDecl *ToProperty;
@@ -4984,22 +5029,15 @@ ExpectedDecl ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
ToTypeSourceInfo, D->getPropertyImplementation()))
return ToProperty;
- Selector ToGetterName, ToSetterName;
- SourceLocation ToGetterNameLoc, ToSetterNameLoc;
- ObjCMethodDecl *ToGetterMethodDecl, *ToSetterMethodDecl;
- ObjCIvarDecl *ToPropertyIvarDecl;
- if (auto Imp = importSeq(
- D->getGetterName(), D->getSetterName(),
- D->getGetterNameLoc(), D->getSetterNameLoc(),
- D->getGetterMethodDecl(), D->getSetterMethodDecl(),
- D->getPropertyIvarDecl()))
- std::tie(
- ToGetterName, ToSetterName,
- ToGetterNameLoc, ToSetterNameLoc,
- ToGetterMethodDecl, ToSetterMethodDecl,
- ToPropertyIvarDecl) = *Imp;
- else
- return Imp.takeError();
+ auto ToGetterName = importChecked(Err, D->getGetterName());
+ auto ToSetterName = importChecked(Err, D->getSetterName());
+ auto ToGetterNameLoc = importChecked(Err, D->getGetterNameLoc());
+ auto ToSetterNameLoc = importChecked(Err, D->getSetterNameLoc());
+ auto ToGetterMethodDecl = importChecked(Err, D->getGetterMethodDecl());
+ auto ToSetterMethodDecl = importChecked(Err, D->getSetterMethodDecl());
+ auto ToPropertyIvarDecl = importChecked(Err, D->getPropertyIvarDecl());
+ if (Err)
+ return std::move(Err);
ToProperty->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToProperty);
@@ -5036,12 +5074,14 @@ ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
= InImpl->FindPropertyImplDecl(Property->getIdentifier(),
Property->getQueryKind());
if (!ToImpl) {
- SourceLocation ToBeginLoc, ToLocation, ToPropertyIvarDeclLoc;
- if (auto Imp = importSeq(
- D->getBeginLoc(), D->getLocation(), D->getPropertyIvarDeclLoc()))
- std::tie(ToBeginLoc, ToLocation, ToPropertyIvarDeclLoc) = *Imp;
- else
- return Imp.takeError();
+
+ Error Err = Error::success();
+ auto ToBeginLoc = importChecked(Err, D->getBeginLoc());
+ auto ToLocation = importChecked(Err, D->getLocation());
+ auto ToPropertyIvarDeclLoc =
+ importChecked(Err, D->getPropertyIvarDeclLoc());
+ if (Err)
+ return std::move(Err);
if (GetImportedOrCreateDecl(ToImpl, D, Importer.getToContext(), DC,
ToBeginLoc,
@@ -5119,20 +5159,16 @@ ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
// Import the type-constraint
if (const TypeConstraint *TC = D->getTypeConstraint()) {
- NestedNameSpecifierLoc ToNNS;
- DeclarationName ToName;
- SourceLocation ToNameLoc;
- NamedDecl *ToFoundDecl;
- ConceptDecl *ToNamedConcept;
- Expr *ToIDC;
- if (auto Imp = importSeq(TC->getNestedNameSpecifierLoc(),
- TC->getConceptNameInfo().getName(), TC->getConceptNameInfo().getLoc(),
- TC->getFoundDecl(), TC->getNamedConcept(),
- TC->getImmediatelyDeclaredConstraint()))
- std::tie(ToNNS, ToName, ToNameLoc, ToFoundDecl, ToNamedConcept,
- ToIDC) = *Imp;
- else
- return Imp.takeError();
+
+ Error Err = Error::success();
+ auto ToNNS = importChecked(Err, TC->getNestedNameSpecifierLoc());
+ auto ToName = importChecked(Err, TC->getConceptNameInfo().getName());
+ auto ToNameLoc = importChecked(Err, TC->getConceptNameInfo().getLoc());
+ auto ToFoundDecl = importChecked(Err, TC->getFoundDecl());
+ auto ToNamedConcept = importChecked(Err, TC->getNamedConcept());
+ auto ToIDC = importChecked(Err, TC->getImmediatelyDeclaredConstraint());
+ if (Err)
+ return std::move(Err);
TemplateArgumentListInfo ToTAInfo;
const auto *ASTTemplateArgs = TC->getTemplateArgsAsWritten();
@@ -5154,18 +5190,15 @@ ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
ExpectedDecl
ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
- DeclarationName ToDeclName;
- SourceLocation ToLocation, ToInnerLocStart;
- QualType ToType;
- TypeSourceInfo *ToTypeSourceInfo;
- if (auto Imp = importSeq(
- D->getDeclName(), D->getLocation(), D->getType(), D->getTypeSourceInfo(),
- D->getInnerLocStart()))
- std::tie(
- ToDeclName, ToLocation, ToType, ToTypeSourceInfo,
- ToInnerLocStart) = *Imp;
- else
- return Imp.takeError();
+
+ Error Err = Error::success();
+ auto ToDeclName = importChecked(Err, D->getDeclName());
+ auto ToLocation = importChecked(Err, D->getLocation());
+ auto ToType = importChecked(Err, D->getType());
+ auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo());
+ auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart());
+ if (Err)
+ return std::move(Err);
// FIXME: Import default argument.
@@ -5245,7 +5278,7 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
Decl *Found = FoundDecl;
auto *FoundTemplate = dyn_cast<ClassTemplateDecl>(Found);
if (FoundTemplate) {
- if (!hasSameVisibilityContext(FoundTemplate, D))
+ if (!hasSameVisibilityContextAndLinkage(FoundTemplate, D))
continue;
if (IsStructuralMatch(D, FoundTemplate)) {
@@ -5508,20 +5541,6 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl(
}
ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
- // If this variable has a definition in the translation unit we're coming
- // from,
- // but this particular declaration is not that definition, import the
- // definition and map to that.
- auto *Definition =
- cast_or_null<VarDecl>(D->getTemplatedDecl()->getDefinition());
- if (Definition && Definition != D->getTemplatedDecl()) {
- if (ExpectedDecl ImportedDefOrErr = import(
- Definition->getDescribedVarTemplate()))
- return Importer.MapImported(D, *ImportedDefOrErr);
- else
- return ImportedDefOrErr.takeError();
- }
-
// Import the major distinguishing characteristics of this variable template.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
@@ -5535,19 +5554,30 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
// We may already have a template of the same name; try to find and match it.
assert(!DC->isFunctionOrMethod() &&
"Variable templates cannot be declared at function scope");
+
SmallVector<NamedDecl *, 4> ConflictingDecls;
auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
+ VarTemplateDecl *FoundByLookup = nullptr;
for (auto *FoundDecl : FoundDecls) {
if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary))
continue;
- Decl *Found = FoundDecl;
- if (VarTemplateDecl *FoundTemplate = dyn_cast<VarTemplateDecl>(Found)) {
+ if (VarTemplateDecl *FoundTemplate = dyn_cast<VarTemplateDecl>(FoundDecl)) {
+ // Use the templated decl, some linkage flags are set only there.
+ if (!hasSameVisibilityContextAndLinkage(FoundTemplate->getTemplatedDecl(),
+ D->getTemplatedDecl()))
+ continue;
if (IsStructuralMatch(D, FoundTemplate)) {
- // The variable templates structurally match; call it the same template.
- Importer.MapImported(D->getTemplatedDecl(),
- FoundTemplate->getTemplatedDecl());
- return Importer.MapImported(D, FoundTemplate);
+ // The Decl in the "From" context has a definition, but in the
+ // "To" context we already have a definition.
+ VarTemplateDecl *FoundDef = getTemplateDefinition(FoundTemplate);
+ if (D->isThisDeclarationADefinition() && FoundDef)
+ // FIXME Check for ODR error if the two definitions have
+ // different initializers?
+ return Importer.MapImported(D, FoundDef);
+
+ FoundByLookup = FoundTemplate;
+ break;
}
ConflictingDecls.push_back(FoundDecl);
}
@@ -5592,6 +5622,18 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
ToVarTD->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToVarTD);
+ if (FoundByLookup) {
+ auto *Recent =
+ const_cast<VarTemplateDecl *>(FoundByLookup->getMostRecentDecl());
+ if (!ToTemplated->getPreviousDecl()) {
+ auto *PrevTemplated =
+ FoundByLookup->getTemplatedDecl()->getMostRecentDecl();
+ if (ToTemplated != PrevTemplated)
+ ToTemplated->setPreviousDecl(PrevTemplated);
+ }
+ ToVarTD->setPreviousDecl(Recent);
+ }
+
if (DTemplated->isThisDeclarationADefinition() &&
!ToTemplated->isThisDeclarationADefinition()) {
// FIXME: Import definition!
@@ -5773,7 +5815,7 @@ ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
continue;
if (auto *FoundTemplate = dyn_cast<FunctionTemplateDecl>(FoundDecl)) {
- if (!hasSameVisibilityContext(FoundTemplate, D))
+ if (!hasSameVisibilityContextAndLinkage(FoundTemplate, D))
continue;
if (IsStructuralMatch(D, FoundTemplate)) {
FunctionTemplateDecl *TemplateWithDef =
@@ -5919,14 +5961,13 @@ ExpectedStmt ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) {
}
ExpectedStmt ASTNodeImporter::VisitDeclStmt(DeclStmt *S) {
- auto Imp = importSeq(S->getDeclGroup(), S->getBeginLoc(), S->getEndLoc());
- if (!Imp)
- return Imp.takeError();
-
- DeclGroupRef ToDG;
- SourceLocation ToBeginLoc, ToEndLoc;
- std::tie(ToDG, ToBeginLoc, ToEndLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToDG = importChecked(Err, S->getDeclGroup());
+ auto ToBeginLoc = importChecked(Err, S->getBeginLoc());
+ auto ToEndLoc = importChecked(Err, S->getEndLoc());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) DeclStmt(ToDG, ToBeginLoc, ToEndLoc);
}
@@ -5958,17 +5999,16 @@ ExpectedStmt ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) {
}
ExpectedStmt ASTNodeImporter::VisitCaseStmt(CaseStmt *S) {
- auto Imp = importSeq(
- S->getLHS(), S->getRHS(), S->getSubStmt(), S->getCaseLoc(),
- S->getEllipsisLoc(), S->getColonLoc());
- if (!Imp)
- return Imp.takeError();
-
- Expr *ToLHS, *ToRHS;
- Stmt *ToSubStmt;
- SourceLocation ToCaseLoc, ToEllipsisLoc, ToColonLoc;
- std::tie(ToLHS, ToRHS, ToSubStmt, ToCaseLoc, ToEllipsisLoc, ToColonLoc) =
- *Imp;
+
+ Error Err = Error::success();
+ auto ToLHS = importChecked(Err, S->getLHS());
+ auto ToRHS = importChecked(Err, S->getRHS());
+ auto ToSubStmt = importChecked(Err, S->getSubStmt());
+ auto ToCaseLoc = importChecked(Err, S->getCaseLoc());
+ auto ToEllipsisLoc = importChecked(Err, S->getEllipsisLoc());
+ auto ToColonLoc = importChecked(Err, S->getColonLoc());
+ if (Err)
+ return std::move(Err);
auto *ToStmt = CaseStmt::Create(Importer.getToContext(), ToLHS, ToRHS,
ToCaseLoc, ToEllipsisLoc, ToColonLoc);
@@ -5978,27 +6018,26 @@ ExpectedStmt ASTNodeImporter::VisitCaseStmt(CaseStmt *S) {
}
ExpectedStmt ASTNodeImporter::VisitDefaultStmt(DefaultStmt *S) {
- auto Imp = importSeq(S->getDefaultLoc(), S->getColonLoc(), S->getSubStmt());
- if (!Imp)
- return Imp.takeError();
- SourceLocation ToDefaultLoc, ToColonLoc;
- Stmt *ToSubStmt;
- std::tie(ToDefaultLoc, ToColonLoc, ToSubStmt) = *Imp;
+ Error Err = Error::success();
+ auto ToDefaultLoc = importChecked(Err, S->getDefaultLoc());
+ auto ToColonLoc = importChecked(Err, S->getColonLoc());
+ auto ToSubStmt = importChecked(Err, S->getSubStmt());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) DefaultStmt(
ToDefaultLoc, ToColonLoc, ToSubStmt);
}
ExpectedStmt ASTNodeImporter::VisitLabelStmt(LabelStmt *S) {
- auto Imp = importSeq(S->getIdentLoc(), S->getDecl(), S->getSubStmt());
- if (!Imp)
- return Imp.takeError();
- SourceLocation ToIdentLoc;
- LabelDecl *ToLabelDecl;
- Stmt *ToSubStmt;
- std::tie(ToIdentLoc, ToLabelDecl, ToSubStmt) = *Imp;
+ Error Err = Error::success();
+ auto ToIdentLoc = importChecked(Err, S->getIdentLoc());
+ auto ToLabelDecl = importChecked(Err, S->getDecl());
+ auto ToSubStmt = importChecked(Err, S->getSubStmt());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) LabelStmt(
ToIdentLoc, ToLabelDecl, ToSubStmt);
@@ -6021,19 +6060,17 @@ ExpectedStmt ASTNodeImporter::VisitAttributedStmt(AttributedStmt *S) {
}
ExpectedStmt ASTNodeImporter::VisitIfStmt(IfStmt *S) {
- auto Imp = importSeq(
- S->getIfLoc(), S->getInit(), S->getConditionVariable(), S->getCond(),
- S->getThen(), S->getElseLoc(), S->getElse());
- if (!Imp)
- return Imp.takeError();
-
- SourceLocation ToIfLoc, ToElseLoc;
- Stmt *ToInit, *ToThen, *ToElse;
- VarDecl *ToConditionVariable;
- Expr *ToCond;
- std::tie(
- ToIfLoc, ToInit, ToConditionVariable, ToCond, ToThen, ToElseLoc, ToElse) =
- *Imp;
+
+ Error Err = Error::success();
+ auto ToIfLoc = importChecked(Err, S->getIfLoc());
+ auto ToInit = importChecked(Err, S->getInit());
+ auto ToConditionVariable = importChecked(Err, S->getConditionVariable());
+ auto ToCond = importChecked(Err, S->getCond());
+ auto ToThen = importChecked(Err, S->getThen());
+ auto ToElseLoc = importChecked(Err, S->getElseLoc());
+ auto ToElse = importChecked(Err, S->getElse());
+ if (Err)
+ return std::move(Err);
return IfStmt::Create(Importer.getToContext(), ToIfLoc, S->isConstexpr(),
ToInit, ToConditionVariable, ToCond, ToThen, ToElseLoc,
@@ -6041,17 +6078,15 @@ ExpectedStmt ASTNodeImporter::VisitIfStmt(IfStmt *S) {
}
ExpectedStmt ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) {
- auto Imp = importSeq(
- S->getInit(), S->getConditionVariable(), S->getCond(),
- S->getBody(), S->getSwitchLoc());
- if (!Imp)
- return Imp.takeError();
-
- Stmt *ToInit, *ToBody;
- VarDecl *ToConditionVariable;
- Expr *ToCond;
- SourceLocation ToSwitchLoc;
- std::tie(ToInit, ToConditionVariable, ToCond, ToBody, ToSwitchLoc) = *Imp;
+
+ Error Err = Error::success();
+ auto ToInit = importChecked(Err, S->getInit());
+ auto ToConditionVariable = importChecked(Err, S->getConditionVariable());
+ auto ToCond = importChecked(Err, S->getCond());
+ auto ToBody = importChecked(Err, S->getBody());
+ auto ToSwitchLoc = importChecked(Err, S->getSwitchLoc());
+ if (Err)
+ return std::move(Err);
auto *ToStmt = SwitchStmt::Create(Importer.getToContext(), ToInit,
ToConditionVariable, ToCond);
@@ -6076,52 +6111,49 @@ ExpectedStmt ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) {
}
ExpectedStmt ASTNodeImporter::VisitWhileStmt(WhileStmt *S) {
- auto Imp = importSeq(
- S->getConditionVariable(), S->getCond(), S->getBody(), S->getWhileLoc());
- if (!Imp)
- return Imp.takeError();
- VarDecl *ToConditionVariable;
- Expr *ToCond;
- Stmt *ToBody;
- SourceLocation ToWhileLoc;
- std::tie(ToConditionVariable, ToCond, ToBody, ToWhileLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToConditionVariable = importChecked(Err, S->getConditionVariable());
+ auto ToCond = importChecked(Err, S->getCond());
+ auto ToBody = importChecked(Err, S->getBody());
+ auto ToWhileLoc = importChecked(Err, S->getWhileLoc());
+ auto ToLParenLoc = importChecked(Err, S->getLParenLoc());
+ auto ToRParenLoc = importChecked(Err, S->getRParenLoc());
+ if (Err)
+ return std::move(Err);
return WhileStmt::Create(Importer.getToContext(), ToConditionVariable, ToCond,
- ToBody, ToWhileLoc);
+ ToBody, ToWhileLoc, ToLParenLoc, ToRParenLoc);
}
ExpectedStmt ASTNodeImporter::VisitDoStmt(DoStmt *S) {
- auto Imp = importSeq(
- S->getBody(), S->getCond(), S->getDoLoc(), S->getWhileLoc(),
- S->getRParenLoc());
- if (!Imp)
- return Imp.takeError();
- Stmt *ToBody;
- Expr *ToCond;
- SourceLocation ToDoLoc, ToWhileLoc, ToRParenLoc;
- std::tie(ToBody, ToCond, ToDoLoc, ToWhileLoc, ToRParenLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToBody = importChecked(Err, S->getBody());
+ auto ToCond = importChecked(Err, S->getCond());
+ auto ToDoLoc = importChecked(Err, S->getDoLoc());
+ auto ToWhileLoc = importChecked(Err, S->getWhileLoc());
+ auto ToRParenLoc = importChecked(Err, S->getRParenLoc());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) DoStmt(
ToBody, ToCond, ToDoLoc, ToWhileLoc, ToRParenLoc);
}
ExpectedStmt ASTNodeImporter::VisitForStmt(ForStmt *S) {
- auto Imp = importSeq(
- S->getInit(), S->getCond(), S->getConditionVariable(), S->getInc(),
- S->getBody(), S->getForLoc(), S->getLParenLoc(), S->getRParenLoc());
- if (!Imp)
- return Imp.takeError();
-
- Stmt *ToInit;
- Expr *ToCond, *ToInc;
- VarDecl *ToConditionVariable;
- Stmt *ToBody;
- SourceLocation ToForLoc, ToLParenLoc, ToRParenLoc;
- std::tie(
- ToInit, ToCond, ToConditionVariable, ToInc, ToBody, ToForLoc,
- ToLParenLoc, ToRParenLoc) = *Imp;
+
+ Error Err = Error::success();
+ auto ToInit = importChecked(Err, S->getInit());
+ auto ToCond = importChecked(Err, S->getCond());
+ auto ToConditionVariable = importChecked(Err, S->getConditionVariable());
+ auto ToInc = importChecked(Err, S->getInc());
+ auto ToBody = importChecked(Err, S->getBody());
+ auto ToForLoc = importChecked(Err, S->getForLoc());
+ auto ToLParenLoc = importChecked(Err, S->getLParenLoc());
+ auto ToRParenLoc = importChecked(Err, S->getRParenLoc());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) ForStmt(
Importer.getToContext(),
@@ -6130,26 +6162,26 @@ ExpectedStmt ASTNodeImporter::VisitForStmt(ForStmt *S) {
}
ExpectedStmt ASTNodeImporter::VisitGotoStmt(GotoStmt *S) {
- auto Imp = importSeq(S->getLabel(), S->getGotoLoc(), S->getLabelLoc());
- if (!Imp)
- return Imp.takeError();
- LabelDecl *ToLabel;
- SourceLocation ToGotoLoc, ToLabelLoc;
- std::tie(ToLabel, ToGotoLoc, ToLabelLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToLabel = importChecked(Err, S->getLabel());
+ auto ToGotoLoc = importChecked(Err, S->getGotoLoc());
+ auto ToLabelLoc = importChecked(Err, S->getLabelLoc());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) GotoStmt(
ToLabel, ToGotoLoc, ToLabelLoc);
}
ExpectedStmt ASTNodeImporter::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
- auto Imp = importSeq(S->getGotoLoc(), S->getStarLoc(), S->getTarget());
- if (!Imp)
- return Imp.takeError();
- SourceLocation ToGotoLoc, ToStarLoc;
- Expr *ToTarget;
- std::tie(ToGotoLoc, ToStarLoc, ToTarget) = *Imp;
+ Error Err = Error::success();
+ auto ToGotoLoc = importChecked(Err, S->getGotoLoc());
+ auto ToStarLoc = importChecked(Err, S->getStarLoc());
+ auto ToTarget = importChecked(Err, S->getTarget());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) IndirectGotoStmt(
ToGotoLoc, ToStarLoc, ToTarget);
@@ -6170,30 +6202,26 @@ ExpectedStmt ASTNodeImporter::VisitBreakStmt(BreakStmt *S) {
}
ExpectedStmt ASTNodeImporter::VisitReturnStmt(ReturnStmt *S) {
- auto Imp = importSeq(
- S->getReturnLoc(), S->getRetValue(), S->getNRVOCandidate());
- if (!Imp)
- return Imp.takeError();
- SourceLocation ToReturnLoc;
- Expr *ToRetValue;
- const VarDecl *ToNRVOCandidate;
- std::tie(ToReturnLoc, ToRetValue, ToNRVOCandidate) = *Imp;
+ Error Err = Error::success();
+ auto ToReturnLoc = importChecked(Err, S->getReturnLoc());
+ auto ToRetValue = importChecked(Err, S->getRetValue());
+ auto ToNRVOCandidate = importChecked(Err, S->getNRVOCandidate());
+ if (Err)
+ return std::move(Err);
return ReturnStmt::Create(Importer.getToContext(), ToReturnLoc, ToRetValue,
ToNRVOCandidate);
}
ExpectedStmt ASTNodeImporter::VisitCXXCatchStmt(CXXCatchStmt *S) {
- auto Imp = importSeq(
- S->getCatchLoc(), S->getExceptionDecl(), S->getHandlerBlock());
- if (!Imp)
- return Imp.takeError();
- SourceLocation ToCatchLoc;
- VarDecl *ToExceptionDecl;
- Stmt *ToHandlerBlock;
- std::tie(ToCatchLoc, ToExceptionDecl, ToHandlerBlock) = *Imp;
+ Error Err = Error::success();
+ auto ToCatchLoc = importChecked(Err, S->getCatchLoc());
+ auto ToExceptionDecl = importChecked(Err, S->getExceptionDecl());
+ auto ToHandlerBlock = importChecked(Err, S->getHandlerBlock());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) CXXCatchStmt (
ToCatchLoc, ToExceptionDecl, ToHandlerBlock);
@@ -6222,24 +6250,22 @@ ExpectedStmt ASTNodeImporter::VisitCXXTryStmt(CXXTryStmt *S) {
}
ExpectedStmt ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
- auto Imp1 = importSeq(
- S->getInit(), S->getRangeStmt(), S->getBeginStmt(), S->getEndStmt(),
- S->getCond(), S->getInc(), S->getLoopVarStmt(), S->getBody());
- if (!Imp1)
- return Imp1.takeError();
- auto Imp2 = importSeq(
- S->getForLoc(), S->getCoawaitLoc(), S->getColonLoc(), S->getRParenLoc());
- if (!Imp2)
- return Imp2.takeError();
-
- DeclStmt *ToRangeStmt, *ToBeginStmt, *ToEndStmt, *ToLoopVarStmt;
- Expr *ToCond, *ToInc;
- Stmt *ToInit, *ToBody;
- std::tie(
- ToInit, ToRangeStmt, ToBeginStmt, ToEndStmt, ToCond, ToInc, ToLoopVarStmt,
- ToBody) = *Imp1;
- SourceLocation ToForLoc, ToCoawaitLoc, ToColonLoc, ToRParenLoc;
- std::tie(ToForLoc, ToCoawaitLoc, ToColonLoc, ToRParenLoc) = *Imp2;
+
+ Error Err = Error::success();
+ auto ToInit = importChecked(Err, S->getInit());
+ auto ToRangeStmt = importChecked(Err, S->getRangeStmt());
+ auto ToBeginStmt = importChecked(Err, S->getBeginStmt());
+ auto ToEndStmt = importChecked(Err, S->getEndStmt());
+ auto ToCond = importChecked(Err, S->getCond());
+ auto ToInc = importChecked(Err, S->getInc());
+ auto ToLoopVarStmt = importChecked(Err, S->getLoopVarStmt());
+ auto ToBody = importChecked(Err, S->getBody());
+ auto ToForLoc = importChecked(Err, S->getForLoc());
+ auto ToCoawaitLoc = importChecked(Err, S->getCoawaitLoc());
+ auto ToColonLoc = importChecked(Err, S->getColonLoc());
+ auto ToRParenLoc = importChecked(Err, S->getRParenLoc());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) CXXForRangeStmt(
ToInit, ToRangeStmt, ToBeginStmt, ToEndStmt, ToCond, ToInc, ToLoopVarStmt,
@@ -6248,16 +6274,14 @@ ExpectedStmt ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
ExpectedStmt
ASTNodeImporter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
- auto Imp = importSeq(
- S->getElement(), S->getCollection(), S->getBody(),
- S->getForLoc(), S->getRParenLoc());
- if (!Imp)
- return Imp.takeError();
-
- Stmt *ToElement, *ToBody;
- Expr *ToCollection;
- SourceLocation ToForLoc, ToRParenLoc;
- std::tie(ToElement, ToCollection, ToBody, ToForLoc, ToRParenLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToElement = importChecked(Err, S->getElement());
+ auto ToCollection = importChecked(Err, S->getCollection());
+ auto ToBody = importChecked(Err, S->getBody());
+ auto ToForLoc = importChecked(Err, S->getForLoc());
+ auto ToRParenLoc = importChecked(Err, S->getRParenLoc());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) ObjCForCollectionStmt(ToElement,
ToCollection,
@@ -6267,16 +6291,14 @@ ASTNodeImporter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
}
ExpectedStmt ASTNodeImporter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
- auto Imp = importSeq(
- S->getAtCatchLoc(), S->getRParenLoc(), S->getCatchParamDecl(),
- S->getCatchBody());
- if (!Imp)
- return Imp.takeError();
- SourceLocation ToAtCatchLoc, ToRParenLoc;
- VarDecl *ToCatchParamDecl;
- Stmt *ToCatchBody;
- std::tie(ToAtCatchLoc, ToRParenLoc, ToCatchParamDecl, ToCatchBody) = *Imp;
+ Error Err = Error::success();
+ auto ToAtCatchLoc = importChecked(Err, S->getAtCatchLoc());
+ auto ToRParenLoc = importChecked(Err, S->getRParenLoc());
+ auto ToCatchParamDecl = importChecked(Err, S->getCatchParamDecl());
+ auto ToCatchBody = importChecked(Err, S->getCatchBody());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) ObjCAtCatchStmt (
ToAtCatchLoc, ToRParenLoc, ToCatchParamDecl, ToCatchBody);
@@ -6294,14 +6316,13 @@ ExpectedStmt ASTNodeImporter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
}
ExpectedStmt ASTNodeImporter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
- auto Imp = importSeq(
- S->getAtTryLoc(), S->getTryBody(), S->getFinallyStmt());
- if (!Imp)
- return Imp.takeError();
- SourceLocation ToAtTryLoc;
- Stmt *ToTryBody, *ToFinallyStmt;
- std::tie(ToAtTryLoc, ToTryBody, ToFinallyStmt) = *Imp;
+ Error Err = Error::success();
+ auto ToAtTryLoc = importChecked(Err, S->getAtTryLoc());
+ auto ToTryBody = importChecked(Err, S->getTryBody());
+ auto ToFinallyStmt = importChecked(Err, S->getFinallyStmt());
+ if (Err)
+ return std::move(Err);
SmallVector<Stmt *, 1> ToCatchStmts(S->getNumCatchStmts());
for (unsigned CI = 0, CE = S->getNumCatchStmts(); CI != CE; ++CI) {
@@ -6318,17 +6339,15 @@ ExpectedStmt ASTNodeImporter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
ToFinallyStmt);
}
-ExpectedStmt ASTNodeImporter::VisitObjCAtSynchronizedStmt
- (ObjCAtSynchronizedStmt *S) {
- auto Imp = importSeq(
- S->getAtSynchronizedLoc(), S->getSynchExpr(), S->getSynchBody());
- if (!Imp)
- return Imp.takeError();
+ExpectedStmt
+ASTNodeImporter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
- SourceLocation ToAtSynchronizedLoc;
- Expr *ToSynchExpr;
- Stmt *ToSynchBody;
- std::tie(ToAtSynchronizedLoc, ToSynchExpr, ToSynchBody) = *Imp;
+ Error Err = Error::success();
+ auto ToAtSynchronizedLoc = importChecked(Err, S->getAtSynchronizedLoc());
+ auto ToSynchExpr = importChecked(Err, S->getSynchExpr());
+ auto ToSynchBody = importChecked(Err, S->getSynchBody());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) ObjCAtSynchronizedStmt(
ToAtSynchronizedLoc, ToSynchExpr, ToSynchBody);
@@ -6367,18 +6386,15 @@ ExpectedStmt ASTNodeImporter::VisitExpr(Expr *E) {
}
ExpectedStmt ASTNodeImporter::VisitVAArgExpr(VAArgExpr *E) {
- auto Imp = importSeq(
- E->getBuiltinLoc(), E->getSubExpr(), E->getWrittenTypeInfo(),
- E->getRParenLoc(), E->getType());
- if (!Imp)
- return Imp.takeError();
-
- SourceLocation ToBuiltinLoc, ToRParenLoc;
- Expr *ToSubExpr;
- TypeSourceInfo *ToWrittenTypeInfo;
- QualType ToType;
- std::tie(ToBuiltinLoc, ToSubExpr, ToWrittenTypeInfo, ToRParenLoc, ToType) =
- *Imp;
+
+ Error Err = Error::success();
+ auto ToBuiltinLoc = importChecked(Err, E->getBuiltinLoc());
+ auto ToSubExpr = importChecked(Err, E->getSubExpr());
+ auto ToWrittenTypeInfo = importChecked(Err, E->getWrittenTypeInfo());
+ auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
+ auto ToType = importChecked(Err, E->getType());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) VAArgExpr(
ToBuiltinLoc, ToSubExpr, ToWrittenTypeInfo, ToRParenLoc, ToType,
@@ -6386,31 +6402,27 @@ ExpectedStmt ASTNodeImporter::VisitVAArgExpr(VAArgExpr *E) {
}
ExpectedStmt ASTNodeImporter::VisitChooseExpr(ChooseExpr *E) {
- auto Imp = importSeq(E->getCond(), E->getLHS(), E->getRHS(),
- E->getBuiltinLoc(), E->getRParenLoc(), E->getType());
- if (!Imp)
- return Imp.takeError();
-
- Expr *ToCond;
- Expr *ToLHS;
- Expr *ToRHS;
- SourceLocation ToBuiltinLoc, ToRParenLoc;
- QualType ToType;
- std::tie(ToCond, ToLHS, ToRHS, ToBuiltinLoc, ToRParenLoc, ToType) = *Imp;
+
+ Error Err = Error::success();
+ auto ToCond = importChecked(Err, E->getCond());
+ auto ToLHS = importChecked(Err, E->getLHS());
+ auto ToRHS = importChecked(Err, E->getRHS());
+ auto ToBuiltinLoc = importChecked(Err, E->getBuiltinLoc());
+ auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
+ auto ToType = importChecked(Err, E->getType());
+ if (Err)
+ return std::move(Err);
ExprValueKind VK = E->getValueKind();
ExprObjectKind OK = E->getObjectKind();
- bool TypeDependent = ToCond->isTypeDependent();
- bool ValueDependent = ToCond->isValueDependent();
-
// The value of CondIsTrue only matters if the value is not
// condition-dependent.
bool CondIsTrue = !E->isConditionDependent() && E->isConditionTrue();
return new (Importer.getToContext())
ChooseExpr(ToBuiltinLoc, ToCond, ToLHS, ToRHS, ToType, VK, OK,
- ToRParenLoc, CondIsTrue, TypeDependent, ValueDependent);
+ ToRParenLoc, CondIsTrue);
}
ExpectedStmt ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) {
@@ -6426,33 +6438,28 @@ ExpectedStmt ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) {
}
ExpectedStmt ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) {
- auto Imp = importSeq(
- E->getBeginLoc(), E->getType(), E->getFunctionName());
- if (!Imp)
- return Imp.takeError();
- SourceLocation ToBeginLoc;
- QualType ToType;
- StringLiteral *ToFunctionName;
- std::tie(ToBeginLoc, ToType, ToFunctionName) = *Imp;
+ Error Err = Error::success();
+ auto ToBeginLoc = importChecked(Err, E->getBeginLoc());
+ auto ToType = importChecked(Err, E->getType());
+ auto ToFunctionName = importChecked(Err, E->getFunctionName());
+ if (Err)
+ return std::move(Err);
return PredefinedExpr::Create(Importer.getToContext(), ToBeginLoc, ToType,
E->getIdentKind(), ToFunctionName);
}
ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
- auto Imp = importSeq(
- E->getQualifierLoc(), E->getTemplateKeywordLoc(), E->getDecl(),
- E->getLocation(), E->getType());
- if (!Imp)
- return Imp.takeError();
-
- NestedNameSpecifierLoc ToQualifierLoc;
- SourceLocation ToTemplateKeywordLoc, ToLocation;
- ValueDecl *ToDecl;
- QualType ToType;
- std::tie(ToQualifierLoc, ToTemplateKeywordLoc, ToDecl, ToLocation, ToType) =
- *Imp;
+
+ Error Err = Error::success();
+ auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc());
+ auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc());
+ auto ToDecl = importChecked(Err, E->getDecl());
+ auto ToLocation = importChecked(Err, E->getLocation());
+ auto ToType = importChecked(Err, E->getType());
+ if (Err)
+ return std::move(Err);
NamedDecl *ToFoundD = nullptr;
if (E->getDecl() != E->getFoundDecl()) {
@@ -6572,6 +6579,20 @@ ExpectedStmt ASTNodeImporter::VisitImaginaryLiteral(ImaginaryLiteral *E) {
*ToSubExprOrErr, *ToTypeOrErr);
}
+ExpectedStmt ASTNodeImporter::VisitFixedPointLiteral(FixedPointLiteral *E) {
+ auto ToTypeOrErr = import(E->getType());
+ if (!ToTypeOrErr)
+ return ToTypeOrErr.takeError();
+
+ ExpectedSLoc ToLocationOrErr = import(E->getLocation());
+ if (!ToLocationOrErr)
+ return ToLocationOrErr.takeError();
+
+ return new (Importer.getToContext()) FixedPointLiteral(
+ Importer.getToContext(), E->getValue(), *ToTypeOrErr, *ToLocationOrErr,
+ Importer.getToContext().getFixedPointScale(*ToTypeOrErr));
+}
+
ExpectedStmt ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) {
ExpectedType ToTypeOrErr = import(E->getType());
if (!ToTypeOrErr)
@@ -6601,17 +6622,14 @@ ExpectedStmt ASTNodeImporter::VisitStringLiteral(StringLiteral *E) {
}
ExpectedStmt ASTNodeImporter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
- auto Imp = importSeq(
- E->getLParenLoc(), E->getTypeSourceInfo(), E->getType(),
- E->getInitializer());
- if (!Imp)
- return Imp.takeError();
-
- SourceLocation ToLParenLoc;
- TypeSourceInfo *ToTypeSourceInfo;
- QualType ToType;
- Expr *ToInitializer;
- std::tie(ToLParenLoc, ToTypeSourceInfo, ToType, ToInitializer) = *Imp;
+
+ Error Err = Error::success();
+ auto ToLParenLoc = importChecked(Err, E->getLParenLoc());
+ auto ToTypeSourceInfo = importChecked(Err, E->getTypeSourceInfo());
+ auto ToType = importChecked(Err, E->getType());
+ auto ToInitializer = importChecked(Err, E->getInitializer());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) CompoundLiteralExpr(
ToLParenLoc, ToTypeSourceInfo, ToType, E->getValueKind(),
@@ -6619,14 +6637,13 @@ ExpectedStmt ASTNodeImporter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
}
ExpectedStmt ASTNodeImporter::VisitAtomicExpr(AtomicExpr *E) {
- auto Imp = importSeq(
- E->getBuiltinLoc(), E->getType(), E->getRParenLoc());
- if (!Imp)
- return Imp.takeError();
- SourceLocation ToBuiltinLoc, ToRParenLoc;
- QualType ToType;
- std::tie(ToBuiltinLoc, ToType, ToRParenLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToBuiltinLoc = importChecked(Err, E->getBuiltinLoc());
+ auto ToType = importChecked(Err, E->getType());
+ auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
+ if (Err)
+ return std::move(Err);
SmallVector<Expr *, 6> ToExprs(E->getNumSubExprs());
if (Error Err = ImportArrayChecked(
@@ -6635,33 +6652,30 @@ ExpectedStmt ASTNodeImporter::VisitAtomicExpr(AtomicExpr *E) {
return std::move(Err);
return new (Importer.getToContext()) AtomicExpr(
+
ToBuiltinLoc, ToExprs, ToType, E->getOp(), ToRParenLoc);
}
ExpectedStmt ASTNodeImporter::VisitAddrLabelExpr(AddrLabelExpr *E) {
- auto Imp = importSeq(
- E->getAmpAmpLoc(), E->getLabelLoc(), E->getLabel(), E->getType());
- if (!Imp)
- return Imp.takeError();
-
- SourceLocation ToAmpAmpLoc, ToLabelLoc;
- LabelDecl *ToLabel;
- QualType ToType;
- std::tie(ToAmpAmpLoc, ToLabelLoc, ToLabel, ToType) = *Imp;
+ Error Err = Error::success();
+ auto ToAmpAmpLoc = importChecked(Err, E->getAmpAmpLoc());
+ auto ToLabelLoc = importChecked(Err, E->getLabelLoc());
+ auto ToLabel = importChecked(Err, E->getLabel());
+ auto ToType = importChecked(Err, E->getType());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) AddrLabelExpr(
ToAmpAmpLoc, ToLabelLoc, ToLabel, ToType);
}
-
ExpectedStmt ASTNodeImporter::VisitConstantExpr(ConstantExpr *E) {
- auto Imp = importSeq(E->getSubExpr());
- if (!Imp)
- return Imp.takeError();
-
- Expr *ToSubExpr;
- std::tie(ToSubExpr) = *Imp;
+ Error Err = Error::success();
+ auto ToSubExpr = importChecked(Err, E->getSubExpr());
+ if (Err)
+ return std::move(Err);
// TODO : Handle APValue::ValueKind that require importing.
+
APValue::ValueKind Kind = E->getResultAPValueKind();
if (Kind == APValue::Int || Kind == APValue::Float ||
Kind == APValue::FixedPoint || Kind == APValue::ComplexFloat ||
@@ -6670,15 +6684,13 @@ ExpectedStmt ASTNodeImporter::VisitConstantExpr(ConstantExpr *E) {
E->getAPValueResult());
return ConstantExpr::Create(Importer.getToContext(), ToSubExpr);
}
-
ExpectedStmt ASTNodeImporter::VisitParenExpr(ParenExpr *E) {
- auto Imp = importSeq(E->getLParen(), E->getRParen(), E->getSubExpr());
- if (!Imp)
- return Imp.takeError();
-
- SourceLocation ToLParen, ToRParen;
- Expr *ToSubExpr;
- std::tie(ToLParen, ToRParen, ToSubExpr) = *Imp;
+ Error Err = Error::success();
+ auto ToLParen = importChecked(Err, E->getLParen());
+ auto ToRParen = importChecked(Err, E->getRParen());
+ auto ToSubExpr = importChecked(Err, E->getSubExpr());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext())
ParenExpr(ToLParen, ToRParen, ToSubExpr);
@@ -6702,45 +6714,42 @@ ExpectedStmt ASTNodeImporter::VisitParenListExpr(ParenListExpr *E) {
}
ExpectedStmt ASTNodeImporter::VisitStmtExpr(StmtExpr *E) {
- auto Imp = importSeq(
- E->getSubStmt(), E->getType(), E->getLParenLoc(), E->getRParenLoc());
- if (!Imp)
- return Imp.takeError();
-
- CompoundStmt *ToSubStmt;
- QualType ToType;
- SourceLocation ToLParenLoc, ToRParenLoc;
- std::tie(ToSubStmt, ToType, ToLParenLoc, ToRParenLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToSubStmt = importChecked(Err, E->getSubStmt());
+ auto ToType = importChecked(Err, E->getType());
+ auto ToLParenLoc = importChecked(Err, E->getLParenLoc());
+ auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
+ if (Err)
+ return std::move(Err);
- return new (Importer.getToContext()) StmtExpr(
- ToSubStmt, ToType, ToLParenLoc, ToRParenLoc);
+ return new (Importer.getToContext())
+ StmtExpr(ToSubStmt, ToType, ToLParenLoc, ToRParenLoc,
+ E->getTemplateDepth());
}
ExpectedStmt ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) {
- auto Imp = importSeq(
- E->getSubExpr(), E->getType(), E->getOperatorLoc());
- if (!Imp)
- return Imp.takeError();
-
- Expr *ToSubExpr;
- QualType ToType;
- SourceLocation ToOperatorLoc;
- std::tie(ToSubExpr, ToType, ToOperatorLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToSubExpr = importChecked(Err, E->getSubExpr());
+ auto ToType = importChecked(Err, E->getType());
+ auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
+ if (Err)
+ return std::move(Err);
- return new (Importer.getToContext()) UnaryOperator(
- ToSubExpr, E->getOpcode(), ToType, E->getValueKind(), E->getObjectKind(),
- ToOperatorLoc, E->canOverflow());
+ return UnaryOperator::Create(
+ Importer.getToContext(), ToSubExpr, E->getOpcode(), ToType,
+ E->getValueKind(), E->getObjectKind(), ToOperatorLoc, E->canOverflow(),
+ E->getFPOptionsOverride());
}
ExpectedStmt
-ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) {
- auto Imp = importSeq(E->getType(), E->getOperatorLoc(), E->getRParenLoc());
- if (!Imp)
- return Imp.takeError();
- QualType ToType;
- SourceLocation ToOperatorLoc, ToRParenLoc;
- std::tie(ToType, ToOperatorLoc, ToRParenLoc) = *Imp;
+ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) {
+ Error Err = Error::success();
+ auto ToType = importChecked(Err, E->getType());
+ auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
+ auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
+ if (Err)
+ return std::move(Err);
if (E->isArgumentType()) {
Expected<TypeSourceInfo *> ToArgumentTypeInfoOrErr =
@@ -6762,53 +6771,49 @@ ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) {
}
ExpectedStmt ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) {
- auto Imp = importSeq(
- E->getLHS(), E->getRHS(), E->getType(), E->getOperatorLoc());
- if (!Imp)
- return Imp.takeError();
-
- Expr *ToLHS, *ToRHS;
- QualType ToType;
- SourceLocation ToOperatorLoc;
- std::tie(ToLHS, ToRHS, ToType, ToOperatorLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToLHS = importChecked(Err, E->getLHS());
+ auto ToRHS = importChecked(Err, E->getRHS());
+ auto ToType = importChecked(Err, E->getType());
+ auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
+ if (Err)
+ return std::move(Err);
- return new (Importer.getToContext()) BinaryOperator(
- ToLHS, ToRHS, E->getOpcode(), ToType, E->getValueKind(),
- E->getObjectKind(), ToOperatorLoc, E->getFPFeatures());
+ return BinaryOperator::Create(
+ Importer.getToContext(), ToLHS, ToRHS, E->getOpcode(), ToType,
+ E->getValueKind(), E->getObjectKind(), ToOperatorLoc,
+ E->getFPFeatures(Importer.getFromContext().getLangOpts()));
}
ExpectedStmt ASTNodeImporter::VisitConditionalOperator(ConditionalOperator *E) {
- auto Imp = importSeq(
- E->getCond(), E->getQuestionLoc(), E->getLHS(), E->getColonLoc(),
- E->getRHS(), E->getType());
- if (!Imp)
- return Imp.takeError();
-
- Expr *ToCond, *ToLHS, *ToRHS;
- SourceLocation ToQuestionLoc, ToColonLoc;
- QualType ToType;
- std::tie(ToCond, ToQuestionLoc, ToLHS, ToColonLoc, ToRHS, ToType) = *Imp;
+ Error Err = Error::success();
+ auto ToCond = importChecked(Err, E->getCond());
+ auto ToQuestionLoc = importChecked(Err, E->getQuestionLoc());
+ auto ToLHS = importChecked(Err, E->getLHS());
+ auto ToColonLoc = importChecked(Err, E->getColonLoc());
+ auto ToRHS = importChecked(Err, E->getRHS());
+ auto ToType = importChecked(Err, E->getType());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) ConditionalOperator(
ToCond, ToQuestionLoc, ToLHS, ToColonLoc, ToRHS, ToType,
E->getValueKind(), E->getObjectKind());
}
-ExpectedStmt ASTNodeImporter::VisitBinaryConditionalOperator(
- BinaryConditionalOperator *E) {
- auto Imp = importSeq(
- E->getCommon(), E->getOpaqueValue(), E->getCond(), E->getTrueExpr(),
- E->getFalseExpr(), E->getQuestionLoc(), E->getColonLoc(), E->getType());
- if (!Imp)
- return Imp.takeError();
-
- Expr *ToCommon, *ToCond, *ToTrueExpr, *ToFalseExpr;
- OpaqueValueExpr *ToOpaqueValue;
- SourceLocation ToQuestionLoc, ToColonLoc;
- QualType ToType;
- std::tie(
- ToCommon, ToOpaqueValue, ToCond, ToTrueExpr, ToFalseExpr, ToQuestionLoc,
- ToColonLoc, ToType) = *Imp;
+ExpectedStmt
+ASTNodeImporter::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) {
+ Error Err = Error::success();
+ auto ToCommon = importChecked(Err, E->getCommon());
+ auto ToOpaqueValue = importChecked(Err, E->getOpaqueValue());
+ auto ToCond = importChecked(Err, E->getCond());
+ auto ToTrueExpr = importChecked(Err, E->getTrueExpr());
+ auto ToFalseExpr = importChecked(Err, E->getFalseExpr());
+ auto ToQuestionLoc = importChecked(Err, E->getQuestionLoc());
+ auto ToColonLoc = importChecked(Err, E->getColonLoc());
+ auto ToType = importChecked(Err, E->getType());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) BinaryConditionalOperator(
ToCommon, ToOpaqueValue, ToCond, ToTrueExpr, ToFalseExpr,
@@ -6817,19 +6822,15 @@ ExpectedStmt ASTNodeImporter::VisitBinaryConditionalOperator(
}
ExpectedStmt ASTNodeImporter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
- auto Imp = importSeq(
- E->getBeginLoc(), E->getQueriedTypeSourceInfo(),
- E->getDimensionExpression(), E->getEndLoc(), E->getType());
- if (!Imp)
- return Imp.takeError();
-
- SourceLocation ToBeginLoc, ToEndLoc;
- TypeSourceInfo *ToQueriedTypeSourceInfo;
- Expr *ToDimensionExpression;
- QualType ToType;
- std::tie(
- ToBeginLoc, ToQueriedTypeSourceInfo, ToDimensionExpression, ToEndLoc,
- ToType) = *Imp;
+ Error Err = Error::success();
+ auto ToBeginLoc = importChecked(Err, E->getBeginLoc());
+ auto ToQueriedTypeSourceInfo =
+ importChecked(Err, E->getQueriedTypeSourceInfo());
+ auto ToDimensionExpression = importChecked(Err, E->getDimensionExpression());
+ auto ToEndLoc = importChecked(Err, E->getEndLoc());
+ auto ToType = importChecked(Err, E->getType());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) ArrayTypeTraitExpr(
ToBeginLoc, E->getTrait(), ToQueriedTypeSourceInfo, E->getValue(),
@@ -6837,15 +6838,13 @@ ExpectedStmt ASTNodeImporter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
}
ExpectedStmt ASTNodeImporter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
- auto Imp = importSeq(
- E->getBeginLoc(), E->getQueriedExpression(), E->getEndLoc(), E->getType());
- if (!Imp)
- return Imp.takeError();
-
- SourceLocation ToBeginLoc, ToEndLoc;
- Expr *ToQueriedExpression;
- QualType ToType;
- std::tie(ToBeginLoc, ToQueriedExpression, ToEndLoc, ToType) = *Imp;
+ Error Err = Error::success();
+ auto ToBeginLoc = importChecked(Err, E->getBeginLoc());
+ auto ToQueriedExpression = importChecked(Err, E->getQueriedExpression());
+ auto ToEndLoc = importChecked(Err, E->getEndLoc());
+ auto ToType = importChecked(Err, E->getType());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) ExpressionTraitExpr(
ToBeginLoc, E->getTrait(), ToQueriedExpression, E->getValue(),
@@ -6853,30 +6852,25 @@ ExpectedStmt ASTNodeImporter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
}
ExpectedStmt ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
- auto Imp = importSeq(
- E->getLocation(), E->getType(), E->getSourceExpr());
- if (!Imp)
- return Imp.takeError();
-
- SourceLocation ToLocation;
- QualType ToType;
- Expr *ToSourceExpr;
- std::tie(ToLocation, ToType, ToSourceExpr) = *Imp;
+ Error Err = Error::success();
+ auto ToLocation = importChecked(Err, E->getLocation());
+ auto ToType = importChecked(Err, E->getType());
+ auto ToSourceExpr = importChecked(Err, E->getSourceExpr());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) OpaqueValueExpr(
ToLocation, ToType, E->getValueKind(), E->getObjectKind(), ToSourceExpr);
}
ExpectedStmt ASTNodeImporter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
- auto Imp = importSeq(
- E->getLHS(), E->getRHS(), E->getType(), E->getRBracketLoc());
- if (!Imp)
- return Imp.takeError();
-
- Expr *ToLHS, *ToRHS;
- SourceLocation ToRBracketLoc;
- QualType ToType;
- std::tie(ToLHS, ToRHS, ToType, ToRBracketLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToLHS = importChecked(Err, E->getLHS());
+ auto ToRHS = importChecked(Err, E->getRHS());
+ auto ToType = importChecked(Err, E->getType());
+ auto ToRBracketLoc = importChecked(Err, E->getRBracketLoc());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) ArraySubscriptExpr(
ToLHS, ToRHS, ToType, E->getValueKind(), E->getObjectKind(),
@@ -6885,22 +6879,22 @@ ExpectedStmt ASTNodeImporter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
ExpectedStmt
ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
- auto Imp = importSeq(
- E->getLHS(), E->getRHS(), E->getType(), E->getComputationLHSType(),
- E->getComputationResultType(), E->getOperatorLoc());
- if (!Imp)
- return Imp.takeError();
-
- Expr *ToLHS, *ToRHS;
- QualType ToType, ToComputationLHSType, ToComputationResultType;
- SourceLocation ToOperatorLoc;
- std::tie(ToLHS, ToRHS, ToType, ToComputationLHSType, ToComputationResultType,
- ToOperatorLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToLHS = importChecked(Err, E->getLHS());
+ auto ToRHS = importChecked(Err, E->getRHS());
+ auto ToType = importChecked(Err, E->getType());
+ auto ToComputationLHSType = importChecked(Err, E->getComputationLHSType());
+ auto ToComputationResultType =
+ importChecked(Err, E->getComputationResultType());
+ auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
+ if (Err)
+ return std::move(Err);
- return new (Importer.getToContext()) CompoundAssignOperator(
- ToLHS, ToRHS, E->getOpcode(), ToType, E->getValueKind(),
- E->getObjectKind(), ToComputationLHSType, ToComputationResultType,
- ToOperatorLoc, E->getFPFeatures());
+ return CompoundAssignOperator::Create(
+ Importer.getToContext(), ToLHS, ToRHS, E->getOpcode(), ToType,
+ E->getValueKind(), E->getObjectKind(), ToOperatorLoc,
+ E->getFPFeatures(Importer.getFromContext().getLangOpts()),
+ ToComputationLHSType, ToComputationResultType);
}
Expected<CXXCastPath>
@@ -6934,15 +6928,12 @@ ExpectedStmt ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
}
ExpectedStmt ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
- auto Imp1 = importSeq(
- E->getType(), E->getSubExpr(), E->getTypeInfoAsWritten());
- if (!Imp1)
- return Imp1.takeError();
-
- QualType ToType;
- Expr *ToSubExpr;
- TypeSourceInfo *ToTypeInfoAsWritten;
- std::tie(ToType, ToSubExpr, ToTypeInfoAsWritten) = *Imp1;
+ Error Err = Error::success();
+ auto ToType = importChecked(Err, E->getType());
+ auto ToSubExpr = importChecked(Err, E->getSubExpr());
+ auto ToTypeInfoAsWritten = importChecked(Err, E->getTypeInfoAsWritten());
+ if (Err)
+ return std::move(Err);
Expected<CXXCastPath> ToBasePathOrErr = ImportCastPath(E);
if (!ToBasePathOrErr)
@@ -7002,11 +6993,13 @@ ExpectedStmt ASTNodeImporter::VisitOffsetOfExpr(OffsetOfExpr *E) {
const OffsetOfNode &FromNode = E->getComponent(I);
SourceLocation ToBeginLoc, ToEndLoc;
+
if (FromNode.getKind() != OffsetOfNode::Base) {
- auto Imp = importSeq(FromNode.getBeginLoc(), FromNode.getEndLoc());
- if (!Imp)
- return Imp.takeError();
- std::tie(ToBeginLoc, ToEndLoc) = *Imp;
+ Error Err = Error::success();
+ ToBeginLoc = importChecked(Err, FromNode.getBeginLoc());
+ ToEndLoc = importChecked(Err, FromNode.getEndLoc());
+ if (Err)
+ return std::move(Err);
}
switch (FromNode.getKind()) {
@@ -7044,16 +7037,13 @@ ExpectedStmt ASTNodeImporter::VisitOffsetOfExpr(OffsetOfExpr *E) {
ToExprs[I] = *ToIndexExprOrErr;
}
- auto Imp = importSeq(
- E->getType(), E->getTypeSourceInfo(), E->getOperatorLoc(),
- E->getRParenLoc());
- if (!Imp)
- return Imp.takeError();
-
- QualType ToType;
- TypeSourceInfo *ToTypeSourceInfo;
- SourceLocation ToOperatorLoc, ToRParenLoc;
- std::tie(ToType, ToTypeSourceInfo, ToOperatorLoc, ToRParenLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToType = importChecked(Err, E->getType());
+ auto ToTypeSourceInfo = importChecked(Err, E->getTypeSourceInfo());
+ auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
+ auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
+ if (Err)
+ return std::move(Err);
return OffsetOfExpr::Create(
Importer.getToContext(), ToType, ToOperatorLoc, ToTypeSourceInfo, ToNodes,
@@ -7061,15 +7051,13 @@ ExpectedStmt ASTNodeImporter::VisitOffsetOfExpr(OffsetOfExpr *E) {
}
ExpectedStmt ASTNodeImporter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
- auto Imp = importSeq(
- E->getType(), E->getOperand(), E->getBeginLoc(), E->getEndLoc());
- if (!Imp)
- return Imp.takeError();
-
- QualType ToType;
- Expr *ToOperand;
- SourceLocation ToBeginLoc, ToEndLoc;
- std::tie(ToType, ToOperand, ToBeginLoc, ToEndLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToType = importChecked(Err, E->getType());
+ auto ToOperand = importChecked(Err, E->getOperand());
+ auto ToBeginLoc = importChecked(Err, E->getBeginLoc());
+ auto ToEndLoc = importChecked(Err, E->getEndLoc());
+ if (Err)
+ return std::move(Err);
CanThrowResult ToCanThrow;
if (E->isValueDependent())
@@ -7082,14 +7070,12 @@ ExpectedStmt ASTNodeImporter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
}
ExpectedStmt ASTNodeImporter::VisitCXXThrowExpr(CXXThrowExpr *E) {
- auto Imp = importSeq(E->getSubExpr(), E->getType(), E->getThrowLoc());
- if (!Imp)
- return Imp.takeError();
-
- Expr *ToSubExpr;
- QualType ToType;
- SourceLocation ToThrowLoc;
- std::tie(ToSubExpr, ToType, ToThrowLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToSubExpr = importChecked(Err, E->getSubExpr());
+ auto ToType = importChecked(Err, E->getType());
+ auto ToThrowLoc = importChecked(Err, E->getThrowLoc());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) CXXThrowExpr(
ToSubExpr, ToType, ToThrowLoc, E->isThrownVariableInScope());
@@ -7129,15 +7115,12 @@ ExpectedStmt ASTNodeImporter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
ExpectedStmt
ASTNodeImporter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
- auto Imp = importSeq(
- E->getType(), E->getTypeSourceInfo(), E->getRParenLoc());
- if (!Imp)
- return Imp.takeError();
-
- QualType ToType;
- TypeSourceInfo *ToTypeSourceInfo;
- SourceLocation ToRParenLoc;
- std::tie(ToType, ToTypeSourceInfo, ToRParenLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToType = importChecked(Err, E->getType());
+ auto ToTypeSourceInfo = importChecked(Err, E->getTypeSourceInfo());
+ auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) CXXScalarValueInitExpr(
ToType, ToTypeSourceInfo, ToRParenLoc);
@@ -7159,18 +7142,15 @@ ASTNodeImporter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
}
ExpectedStmt
+
ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) {
- auto Imp = importSeq(
- E->getConstructor(), E->getType(), E->getTypeSourceInfo(),
- E->getParenOrBraceRange());
- if (!Imp)
- return Imp.takeError();
-
- CXXConstructorDecl *ToConstructor;
- QualType ToType;
- TypeSourceInfo *ToTypeSourceInfo;
- SourceRange ToParenOrBraceRange;
- std::tie(ToConstructor, ToType, ToTypeSourceInfo, ToParenOrBraceRange) = *Imp;
+ Error Err = Error::success();
+ auto ToConstructor = importChecked(Err, E->getConstructor());
+ auto ToType = importChecked(Err, E->getType());
+ auto ToTypeSourceInfo = importChecked(Err, E->getTypeSourceInfo());
+ auto ToParenOrBraceRange = importChecked(Err, E->getParenOrBraceRange());
+ if (Err)
+ return std::move(Err);
SmallVector<Expr *, 8> ToArgs(E->getNumArgs());
if (Error Err = ImportContainerChecked(E->arguments(), ToArgs))
@@ -7189,14 +7169,11 @@ ExpectedDecl ASTNodeImporter::VisitLifetimeExtendedTemporaryDecl(
if (Error Err = ImportDeclContext(D, DC, LexicalDC))
return std::move(Err);
- auto Imp = importSeq(D->getTemporaryExpr(), D->getExtendingDecl());
- // FIXME: the APValue should be imported as well if present.
- if (!Imp)
- return Imp.takeError();
-
- Expr *Temporary;
- ValueDecl *ExtendingDecl;
- std::tie(Temporary, ExtendingDecl) = *Imp;
+ Error Err = Error::success();
+ auto Temporary = importChecked(Err, D->getTemporaryExpr());
+ auto ExtendingDecl = importChecked(Err, D->getExtendingDecl());
+ if (Err)
+ return std::move(Err);
// FIXME: Should ManglingNumber get numbers associated with 'to' context?
LifetimeExtendedTemporaryDecl *To;
@@ -7211,17 +7188,15 @@ ExpectedDecl ASTNodeImporter::VisitLifetimeExtendedTemporaryDecl(
ExpectedStmt
ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
- auto Imp = importSeq(E->getType(),
- E->getLifetimeExtendedTemporaryDecl() ? nullptr
- : E->getSubExpr(),
- E->getLifetimeExtendedTemporaryDecl());
- if (!Imp)
- return Imp.takeError();
-
- QualType ToType;
- Expr *ToTemporaryExpr;
- LifetimeExtendedTemporaryDecl *ToMaterializedDecl;
- std::tie(ToType, ToTemporaryExpr, ToMaterializedDecl) = *Imp;
+ Error Err = Error::success();
+ auto ToType = importChecked(Err, E->getType());
+ Expr *ToTemporaryExpr = importChecked(
+ Err, E->getLifetimeExtendedTemporaryDecl() ? nullptr : E->getSubExpr());
+ auto ToMaterializedDecl =
+ importChecked(Err, E->getLifetimeExtendedTemporaryDecl());
+ if (Err)
+ return std::move(Err);
+
if (!ToTemporaryExpr)
ToTemporaryExpr = cast<Expr>(ToMaterializedDecl->getTemporaryExpr());
@@ -7233,29 +7208,25 @@ ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
}
ExpectedStmt ASTNodeImporter::VisitPackExpansionExpr(PackExpansionExpr *E) {
- auto Imp = importSeq(
- E->getType(), E->getPattern(), E->getEllipsisLoc());
- if (!Imp)
- return Imp.takeError();
-
- QualType ToType;
- Expr *ToPattern;
- SourceLocation ToEllipsisLoc;
- std::tie(ToType, ToPattern, ToEllipsisLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToType = importChecked(Err, E->getType());
+ auto ToPattern = importChecked(Err, E->getPattern());
+ auto ToEllipsisLoc = importChecked(Err, E->getEllipsisLoc());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) PackExpansionExpr(
ToType, ToPattern, ToEllipsisLoc, E->getNumExpansions());
}
ExpectedStmt ASTNodeImporter::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
- auto Imp = importSeq(
- E->getOperatorLoc(), E->getPack(), E->getPackLoc(), E->getRParenLoc());
- if (!Imp)
- return Imp.takeError();
-
- SourceLocation ToOperatorLoc, ToPackLoc, ToRParenLoc;
- NamedDecl *ToPack;
- std::tie(ToOperatorLoc, ToPack, ToPackLoc, ToRParenLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
+ auto ToPack = importChecked(Err, E->getPack());
+ auto ToPackLoc = importChecked(Err, E->getPackLoc());
+ auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
+ if (Err)
+ return std::move(Err);
Optional<unsigned> Length;
if (!E->isValueDependent())
@@ -7277,23 +7248,19 @@ ExpectedStmt ASTNodeImporter::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
ExpectedStmt ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *E) {
- auto Imp = importSeq(
- E->getOperatorNew(), E->getOperatorDelete(), E->getTypeIdParens(),
- E->getArraySize(), E->getInitializer(), E->getType(),
- E->getAllocatedTypeSourceInfo(), E->getSourceRange(),
- E->getDirectInitRange());
- if (!Imp)
- return Imp.takeError();
-
- FunctionDecl *ToOperatorNew, *ToOperatorDelete;
- SourceRange ToTypeIdParens, ToSourceRange, ToDirectInitRange;
- Optional<Expr *> ToArraySize;
- Expr *ToInitializer;
- QualType ToType;
- TypeSourceInfo *ToAllocatedTypeSourceInfo;
- std::tie(
- ToOperatorNew, ToOperatorDelete, ToTypeIdParens, ToArraySize, ToInitializer,
- ToType, ToAllocatedTypeSourceInfo, ToSourceRange, ToDirectInitRange) = *Imp;
+ Error Err = Error::success();
+ auto ToOperatorNew = importChecked(Err, E->getOperatorNew());
+ auto ToOperatorDelete = importChecked(Err, E->getOperatorDelete());
+ auto ToTypeIdParens = importChecked(Err, E->getTypeIdParens());
+ auto ToArraySize = importChecked(Err, E->getArraySize());
+ auto ToInitializer = importChecked(Err, E->getInitializer());
+ auto ToType = importChecked(Err, E->getType());
+ auto ToAllocatedTypeSourceInfo =
+ importChecked(Err, E->getAllocatedTypeSourceInfo());
+ auto ToSourceRange = importChecked(Err, E->getSourceRange());
+ auto ToDirectInitRange = importChecked(Err, E->getDirectInitRange());
+ if (Err)
+ return std::move(Err);
SmallVector<Expr *, 4> ToPlacementArgs(E->getNumPlacementArgs());
if (Error Err =
@@ -7309,16 +7276,13 @@ ExpectedStmt ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *E) {
}
ExpectedStmt ASTNodeImporter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
- auto Imp = importSeq(
- E->getType(), E->getOperatorDelete(), E->getArgument(), E->getBeginLoc());
- if (!Imp)
- return Imp.takeError();
-
- QualType ToType;
- FunctionDecl *ToOperatorDelete;
- Expr *ToArgument;
- SourceLocation ToBeginLoc;
- std::tie(ToType, ToOperatorDelete, ToArgument, ToBeginLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToType = importChecked(Err, E->getType());
+ auto ToOperatorDelete = importChecked(Err, E->getOperatorDelete());
+ auto ToArgument = importChecked(Err, E->getArgument());
+ auto ToBeginLoc = importChecked(Err, E->getBeginLoc());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) CXXDeleteExpr(
ToType, E->isGlobalDelete(), E->isArrayForm(), E->isArrayFormAsWritten(),
@@ -7327,17 +7291,13 @@ ExpectedStmt ASTNodeImporter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
}
ExpectedStmt ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
- auto Imp = importSeq(
- E->getType(), E->getLocation(), E->getConstructor(),
- E->getParenOrBraceRange());
- if (!Imp)
- return Imp.takeError();
-
- QualType ToType;
- SourceLocation ToLocation;
- CXXConstructorDecl *ToConstructor;
- SourceRange ToParenOrBraceRange;
- std::tie(ToType, ToLocation, ToConstructor, ToParenOrBraceRange) = *Imp;
+ Error Err = Error::success();
+ auto ToType = importChecked(Err, E->getType());
+ auto ToLocation = importChecked(Err, E->getLocation());
+ auto ToConstructor = importChecked(Err, E->getConstructor());
+ auto ToParenOrBraceRange = importChecked(Err, E->getParenOrBraceRange());
+ if (Err)
+ return std::move(Err);
SmallVector<Expr *, 6> ToArgs(E->getNumArgs());
if (Error Err = ImportContainerChecked(E->arguments(), ToArgs))
@@ -7366,15 +7326,12 @@ ExpectedStmt ASTNodeImporter::VisitExprWithCleanups(ExprWithCleanups *E) {
}
ExpectedStmt ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
- auto Imp = importSeq(
- E->getCallee(), E->getType(), E->getRParenLoc());
- if (!Imp)
- return Imp.takeError();
-
- Expr *ToCallee;
- QualType ToType;
- SourceLocation ToRParenLoc;
- std::tie(ToCallee, ToType, ToRParenLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToCallee = importChecked(Err, E->getCallee());
+ auto ToType = importChecked(Err, E->getType());
+ auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
+ if (Err)
+ return std::move(Err);
SmallVector<Expr *, 4> ToArgs(E->getNumArgs());
if (Error Err = ImportContainerChecked(E->arguments(), ToArgs))
@@ -7411,30 +7368,18 @@ ExpectedStmt ASTNodeImporter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
}
ExpectedStmt ASTNodeImporter::VisitMemberExpr(MemberExpr *E) {
- auto Imp1 = importSeq(
- E->getBase(), E->getOperatorLoc(), E->getQualifierLoc(),
- E->getTemplateKeywordLoc(), E->getMemberDecl(), E->getType());
- if (!Imp1)
- return Imp1.takeError();
-
- Expr *ToBase;
- SourceLocation ToOperatorLoc, ToTemplateKeywordLoc;
- NestedNameSpecifierLoc ToQualifierLoc;
- ValueDecl *ToMemberDecl;
- QualType ToType;
- std::tie(
- ToBase, ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc, ToMemberDecl,
- ToType) = *Imp1;
-
- auto Imp2 = importSeq(
- E->getFoundDecl().getDecl(), E->getMemberNameInfo().getName(),
- E->getMemberNameInfo().getLoc(), E->getLAngleLoc(), E->getRAngleLoc());
- if (!Imp2)
- return Imp2.takeError();
- NamedDecl *ToDecl;
- DeclarationName ToName;
- SourceLocation ToLoc, ToLAngleLoc, ToRAngleLoc;
- std::tie(ToDecl, ToName, ToLoc, ToLAngleLoc, ToRAngleLoc) = *Imp2;
+ Error Err = Error::success();
+ auto ToBase = importChecked(Err, E->getBase());
+ auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
+ auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc());
+ auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc());
+ auto ToMemberDecl = importChecked(Err, E->getMemberDecl());
+ auto ToType = importChecked(Err, E->getType());
+ auto ToDecl = importChecked(Err, E->getFoundDecl().getDecl());
+ auto ToName = importChecked(Err, E->getMemberNameInfo().getName());
+ auto ToLoc = importChecked(Err, E->getMemberNameInfo().getLoc());
+ if (Err)
+ return std::move(Err);
DeclAccessPair ToFoundDecl =
DeclAccessPair::make(ToDecl, E->getFoundDecl().getAccess());
@@ -7459,19 +7404,15 @@ ExpectedStmt ASTNodeImporter::VisitMemberExpr(MemberExpr *E) {
ExpectedStmt
ASTNodeImporter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
- auto Imp = importSeq(
- E->getBase(), E->getOperatorLoc(), E->getQualifierLoc(),
- E->getScopeTypeInfo(), E->getColonColonLoc(), E->getTildeLoc());
- if (!Imp)
- return Imp.takeError();
-
- Expr *ToBase;
- SourceLocation ToOperatorLoc, ToColonColonLoc, ToTildeLoc;
- NestedNameSpecifierLoc ToQualifierLoc;
- TypeSourceInfo *ToScopeTypeInfo;
- std::tie(
- ToBase, ToOperatorLoc, ToQualifierLoc, ToScopeTypeInfo, ToColonColonLoc,
- ToTildeLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToBase = importChecked(Err, E->getBase());
+ auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
+ auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc());
+ auto ToScopeTypeInfo = importChecked(Err, E->getScopeTypeInfo());
+ auto ToColonColonLoc = importChecked(Err, E->getColonColonLoc());
+ auto ToTildeLoc = importChecked(Err, E->getTildeLoc());
+ if (Err)
+ return std::move(Err);
PseudoDestructorTypeStorage Storage;
if (IdentifierInfo *FromII = E->getDestroyedTypeIdentifier()) {
@@ -7494,19 +7435,15 @@ ASTNodeImporter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
ExpectedStmt ASTNodeImporter::VisitCXXDependentScopeMemberExpr(
CXXDependentScopeMemberExpr *E) {
- auto Imp = importSeq(
- E->getType(), E->getOperatorLoc(), E->getQualifierLoc(),
- E->getTemplateKeywordLoc(), E->getFirstQualifierFoundInScope());
- if (!Imp)
- return Imp.takeError();
-
- QualType ToType;
- SourceLocation ToOperatorLoc, ToTemplateKeywordLoc;
- NestedNameSpecifierLoc ToQualifierLoc;
- NamedDecl *ToFirstQualifierFoundInScope;
- std::tie(
- ToType, ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc,
- ToFirstQualifierFoundInScope) = *Imp;
+ Error Err = Error::success();
+ auto ToType = importChecked(Err, E->getType());
+ auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
+ auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc());
+ auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc());
+ auto ToFirstQualifierFoundInScope =
+ importChecked(Err, E->getFirstQualifierFoundInScope());
+ if (Err)
+ return std::move(Err);
Expr *ToBase = nullptr;
if (!E->isImplicitAccess()) {
@@ -7517,22 +7454,23 @@ ExpectedStmt ASTNodeImporter::VisitCXXDependentScopeMemberExpr(
}
TemplateArgumentListInfo ToTAInfo, *ResInfo = nullptr;
+
if (E->hasExplicitTemplateArgs()) {
- if (Error Err = ImportTemplateArgumentListInfo(
- E->getLAngleLoc(), E->getRAngleLoc(), E->template_arguments(),
- ToTAInfo))
+ if (Error Err =
+ ImportTemplateArgumentListInfo(E->getLAngleLoc(), E->getRAngleLoc(),
+ E->template_arguments(), ToTAInfo))
return std::move(Err);
ResInfo = &ToTAInfo;
}
+ auto ToMember = importChecked(Err, E->getMember());
+ auto ToMemberLoc = importChecked(Err, E->getMemberLoc());
+ if (Err)
+ return std::move(Err);
+ DeclarationNameInfo ToMemberNameInfo(ToMember, ToMemberLoc);
- auto ToMemberNameInfoOrErr = importSeq(E->getMember(), E->getMemberLoc());
- if (!ToMemberNameInfoOrErr)
- return ToMemberNameInfoOrErr.takeError();
- DeclarationNameInfo ToMemberNameInfo(
- std::get<0>(*ToMemberNameInfoOrErr), std::get<1>(*ToMemberNameInfoOrErr));
// Import additional name location/type info.
- if (Error Err = ImportDeclarationNameLoc(
- E->getMemberNameInfo(), ToMemberNameInfo))
+ if (Error Err =
+ ImportDeclarationNameLoc(E->getMemberNameInfo(), ToMemberNameInfo))
return std::move(Err);
return CXXDependentScopeMemberExpr::Create(
@@ -7543,17 +7481,15 @@ ExpectedStmt ASTNodeImporter::VisitCXXDependentScopeMemberExpr(
ExpectedStmt
ASTNodeImporter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
- auto Imp = importSeq(E->getQualifierLoc(), E->getTemplateKeywordLoc(),
- E->getDeclName(), E->getNameInfo().getLoc(),
- E->getLAngleLoc(), E->getRAngleLoc());
- if (!Imp)
- return Imp.takeError();
-
- NestedNameSpecifierLoc ToQualifierLoc;
- SourceLocation ToTemplateKeywordLoc, ToNameLoc, ToLAngleLoc, ToRAngleLoc;
- DeclarationName ToDeclName;
- std::tie(ToQualifierLoc, ToTemplateKeywordLoc, ToDeclName, ToNameLoc,
- ToLAngleLoc, ToRAngleLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc());
+ auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc());
+ auto ToDeclName = importChecked(Err, E->getDeclName());
+ auto ToNameLoc = importChecked(Err, E->getNameInfo().getLoc());
+ auto ToLAngleLoc = importChecked(Err, E->getLAngleLoc());
+ auto ToRAngleLoc = importChecked(Err, E->getRAngleLoc());
+ if (Err)
+ return std::move(Err);
DeclarationNameInfo ToNameInfo(ToDeclName, ToNameLoc);
if (Error Err = ImportDeclarationNameLoc(E->getNameInfo(), ToNameInfo))
@@ -7575,14 +7511,12 @@ ASTNodeImporter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
ExpectedStmt ASTNodeImporter::VisitCXXUnresolvedConstructExpr(
CXXUnresolvedConstructExpr *E) {
- auto Imp = importSeq(
- E->getLParenLoc(), E->getRParenLoc(), E->getTypeSourceInfo());
- if (!Imp)
- return Imp.takeError();
-
- SourceLocation ToLParenLoc, ToRParenLoc;
- TypeSourceInfo *ToTypeSourceInfo;
- std::tie(ToLParenLoc, ToRParenLoc, ToTypeSourceInfo) = *Imp;
+ Error Err = Error::success();
+ auto ToLParenLoc = importChecked(Err, E->getLParenLoc());
+ auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
+ auto ToTypeSourceInfo = importChecked(Err, E->getTypeSourceInfo());
+ if (Err)
+ return std::move(Err);
SmallVector<Expr *, 8> ToArgs(E->arg_size());
if (Error Err =
@@ -7604,11 +7538,13 @@ ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
if (!ToQualifierLocOrErr)
return ToQualifierLocOrErr.takeError();
- auto ToNameInfoOrErr = importSeq(E->getName(), E->getNameLoc());
- if (!ToNameInfoOrErr)
- return ToNameInfoOrErr.takeError();
- DeclarationNameInfo ToNameInfo(
- std::get<0>(*ToNameInfoOrErr), std::get<1>(*ToNameInfoOrErr));
+ Error Err = Error::success();
+ auto ToName = importChecked(Err, E->getName());
+ auto ToNameLoc = importChecked(Err, E->getNameLoc());
+ if (Err)
+ return std::move(Err);
+ DeclarationNameInfo ToNameInfo(ToName, ToNameLoc);
+
// Import additional name location/type info.
if (Error Err = ImportDeclarationNameLoc(E->getNameInfo(), ToNameInfo))
return std::move(Err);
@@ -7645,21 +7581,17 @@ ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
ExpectedStmt
ASTNodeImporter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
- auto Imp1 = importSeq(
- E->getType(), E->getOperatorLoc(), E->getQualifierLoc(),
- E->getTemplateKeywordLoc());
- if (!Imp1)
- return Imp1.takeError();
-
- QualType ToType;
- SourceLocation ToOperatorLoc, ToTemplateKeywordLoc;
- NestedNameSpecifierLoc ToQualifierLoc;
- std::tie(ToType, ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc) = *Imp1;
-
- auto Imp2 = importSeq(E->getName(), E->getNameLoc());
- if (!Imp2)
- return Imp2.takeError();
- DeclarationNameInfo ToNameInfo(std::get<0>(*Imp2), std::get<1>(*Imp2));
+ Error Err = Error::success();
+ auto ToType = importChecked(Err, E->getType());
+ auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
+ auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc());
+ auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc());
+ auto ToName = importChecked(Err, E->getName());
+ auto ToNameLoc = importChecked(Err, E->getNameLoc());
+ if (Err)
+ return std::move(Err);
+
+ DeclarationNameInfo ToNameInfo(ToName, ToNameLoc);
// Import additional name location/type info.
if (Error Err = ImportDeclarationNameLoc(E->getNameInfo(), ToNameInfo))
return std::move(Err);
@@ -7696,14 +7628,12 @@ ASTNodeImporter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
}
ExpectedStmt ASTNodeImporter::VisitCallExpr(CallExpr *E) {
- auto Imp = importSeq(E->getCallee(), E->getType(), E->getRParenLoc());
- if (!Imp)
- return Imp.takeError();
-
- Expr *ToCallee;
- QualType ToType;
- SourceLocation ToRParenLoc;
- std::tie(ToCallee, ToType, ToRParenLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToCallee = importChecked(Err, E->getCallee());
+ auto ToType = importChecked(Err, E->getType());
+ auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
+ if (Err)
+ return std::move(Err);
unsigned NumArgs = E->getNumArgs();
llvm::SmallVector<Expr *, 2> ToArgs(NumArgs);
@@ -7733,44 +7663,32 @@ ExpectedStmt ASTNodeImporter::VisitLambdaExpr(LambdaExpr *E) {
if (!ToCallOpOrErr)
return ToCallOpOrErr.takeError();
- SmallVector<LambdaCapture, 8> ToCaptures;
- ToCaptures.reserve(E->capture_size());
- for (const auto &FromCapture : E->captures()) {
- if (auto ToCaptureOrErr = import(FromCapture))
- ToCaptures.push_back(*ToCaptureOrErr);
- else
- return ToCaptureOrErr.takeError();
- }
-
SmallVector<Expr *, 8> ToCaptureInits(E->capture_size());
if (Error Err = ImportContainerChecked(E->capture_inits(), ToCaptureInits))
return std::move(Err);
- auto Imp = importSeq(
- E->getIntroducerRange(), E->getCaptureDefaultLoc(), E->getEndLoc());
- if (!Imp)
- return Imp.takeError();
-
- SourceRange ToIntroducerRange;
- SourceLocation ToCaptureDefaultLoc, ToEndLoc;
- std::tie(ToIntroducerRange, ToCaptureDefaultLoc, ToEndLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToIntroducerRange = importChecked(Err, E->getIntroducerRange());
+ auto ToCaptureDefaultLoc = importChecked(Err, E->getCaptureDefaultLoc());
+ auto ToEndLoc = importChecked(Err, E->getEndLoc());
+ if (Err)
+ return std::move(Err);
- return LambdaExpr::Create(
- Importer.getToContext(), ToClass, ToIntroducerRange,
- E->getCaptureDefault(), ToCaptureDefaultLoc, ToCaptures,
- E->hasExplicitParameters(), E->hasExplicitResultType(), ToCaptureInits,
- ToEndLoc, E->containsUnexpandedParameterPack());
+ return LambdaExpr::Create(Importer.getToContext(), ToClass, ToIntroducerRange,
+ E->getCaptureDefault(), ToCaptureDefaultLoc,
+ E->hasExplicitParameters(),
+ E->hasExplicitResultType(), ToCaptureInits,
+ ToEndLoc, E->containsUnexpandedParameterPack());
}
ExpectedStmt ASTNodeImporter::VisitInitListExpr(InitListExpr *E) {
- auto Imp = importSeq(E->getLBraceLoc(), E->getRBraceLoc(), E->getType());
- if (!Imp)
- return Imp.takeError();
-
- SourceLocation ToLBraceLoc, ToRBraceLoc;
- QualType ToType;
- std::tie(ToLBraceLoc, ToRBraceLoc, ToType) = *Imp;
+ Error Err = Error::success();
+ auto ToLBraceLoc = importChecked(Err, E->getLBraceLoc());
+ auto ToRBraceLoc = importChecked(Err, E->getRBraceLoc());
+ auto ToType = importChecked(Err, E->getType());
+ if (Err)
+ return std::move(Err);
SmallVector<Expr *, 4> ToExprs(E->getNumInits());
if (Error Err = ImportContainerChecked(E->inits(), ToExprs))
@@ -7825,14 +7743,12 @@ ExpectedStmt ASTNodeImporter::VisitCXXStdInitializerListExpr(
ExpectedStmt ASTNodeImporter::VisitCXXInheritedCtorInitExpr(
CXXInheritedCtorInitExpr *E) {
- auto Imp = importSeq(E->getLocation(), E->getType(), E->getConstructor());
- if (!Imp)
- return Imp.takeError();
-
- SourceLocation ToLocation;
- QualType ToType;
- CXXConstructorDecl *ToConstructor;
- std::tie(ToLocation, ToType, ToConstructor) = *Imp;
+ Error Err = Error::success();
+ auto ToLocation = importChecked(Err, E->getLocation());
+ auto ToType = importChecked(Err, E->getType());
+ auto ToConstructor = importChecked(Err, E->getConstructor());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) CXXInheritedCtorInitExpr(
ToLocation, ToType, ToConstructor, E->constructsVBase(),
@@ -7840,13 +7756,12 @@ ExpectedStmt ASTNodeImporter::VisitCXXInheritedCtorInitExpr(
}
ExpectedStmt ASTNodeImporter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) {
- auto Imp = importSeq(E->getType(), E->getCommonExpr(), E->getSubExpr());
- if (!Imp)
- return Imp.takeError();
-
- QualType ToType;
- Expr *ToCommonExpr, *ToSubExpr;
- std::tie(ToType, ToCommonExpr, ToSubExpr) = *Imp;
+ Error Err = Error::success();
+ auto ToType = importChecked(Err, E->getType());
+ auto ToCommonExpr = importChecked(Err, E->getCommonExpr());
+ auto ToSubExpr = importChecked(Err, E->getSubExpr());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) ArrayInitLoopExpr(
ToType, ToCommonExpr, ToSubExpr);
@@ -7877,20 +7792,15 @@ ExpectedStmt ASTNodeImporter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) {
}
ExpectedStmt ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
- auto Imp = importSeq(
- E->getType(), E->getSubExpr(), E->getTypeInfoAsWritten(),
- E->getOperatorLoc(), E->getRParenLoc(), E->getAngleBrackets());
- if (!Imp)
- return Imp.takeError();
-
- QualType ToType;
- Expr *ToSubExpr;
- TypeSourceInfo *ToTypeInfoAsWritten;
- SourceLocation ToOperatorLoc, ToRParenLoc;
- SourceRange ToAngleBrackets;
- std::tie(
- ToType, ToSubExpr, ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc,
- ToAngleBrackets) = *Imp;
+ Error Err = Error::success();
+ auto ToType = importChecked(Err, E->getType());
+ auto ToSubExpr = importChecked(Err, E->getSubExpr());
+ auto ToTypeInfoAsWritten = importChecked(Err, E->getTypeInfoAsWritten());
+ auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
+ auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
+ auto ToAngleBrackets = importChecked(Err, E->getAngleBrackets());
+ if (Err)
+ return std::move(Err);
ExprValueKind VK = E->getValueKind();
CastKind CK = E->getCastKind();
@@ -7922,30 +7832,25 @@ ExpectedStmt ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
ExpectedStmt ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr(
SubstNonTypeTemplateParmExpr *E) {
- auto Imp = importSeq(
- E->getType(), E->getExprLoc(), E->getParameter(), E->getReplacement());
- if (!Imp)
- return Imp.takeError();
-
- QualType ToType;
- SourceLocation ToExprLoc;
- NonTypeTemplateParmDecl *ToParameter;
- Expr *ToReplacement;
- std::tie(ToType, ToExprLoc, ToParameter, ToReplacement) = *Imp;
+ Error Err = Error::success();
+ auto ToType = importChecked(Err, E->getType());
+ auto ToExprLoc = importChecked(Err, E->getExprLoc());
+ auto ToParameter = importChecked(Err, E->getParameter());
+ auto ToReplacement = importChecked(Err, E->getReplacement());
+ if (Err)
+ return std::move(Err);
return new (Importer.getToContext()) SubstNonTypeTemplateParmExpr(
ToType, E->getValueKind(), ToExprLoc, ToParameter, ToReplacement);
}
ExpectedStmt ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) {
- auto Imp = importSeq(
- E->getType(), E->getBeginLoc(), E->getEndLoc());
- if (!Imp)
- return Imp.takeError();
-
- QualType ToType;
- SourceLocation ToBeginLoc, ToEndLoc;
- std::tie(ToType, ToBeginLoc, ToEndLoc) = *Imp;
+ Error Err = Error::success();
+ auto ToType = importChecked(Err, E->getType());
+ auto ToBeginLoc = importChecked(Err, E->getBeginLoc());
+ auto ToEndLoc = importChecked(Err, E->getEndLoc());
+ if (Err)
+ return std::move(Err);
SmallVector<TypeSourceInfo *, 4> ToArgs(E->getNumArgs());
if (Error Err = ImportContainerChecked(E->getArgs(), ToArgs))
@@ -8087,6 +7992,18 @@ void ASTImporter::RegisterImportedDecl(Decl *FromD, Decl *ToD) {
MapImported(FromD, ToD);
}
+llvm::Expected<ExprWithCleanups::CleanupObject>
+ASTImporter::Import(ExprWithCleanups::CleanupObject From) {
+ if (auto *CLE = From.dyn_cast<CompoundLiteralExpr *>()) {
+ if (Expected<Expr *> R = Import(CLE))
+ return ExprWithCleanups::CleanupObject(cast<CompoundLiteralExpr>(*R));
+ }
+
+ // FIXME: Handle BlockDecl when we implement importing BlockExpr in
+ // ASTNodeImporter.
+ return make_error<ImportError>(ImportError::UnsupportedConstruct);
+}
+
Expected<QualType> ASTImporter::Import(QualType FromT) {
if (FromT.isNull())
return QualType{};
@@ -8128,12 +8045,47 @@ Expected<TypeSourceInfo *> ASTImporter::Import(TypeSourceInfo *FromTSI) {
}
Expected<Attr *> ASTImporter::Import(const Attr *FromAttr) {
- Attr *ToAttr = FromAttr->clone(ToContext);
- if (auto ToRangeOrErr = Import(FromAttr->getRange()))
- ToAttr->setRange(*ToRangeOrErr);
- else
- return ToRangeOrErr.takeError();
+ Attr *ToAttr = nullptr;
+ SourceRange ToRange;
+ if (Error Err = importInto(ToRange, FromAttr->getRange()))
+ return std::move(Err);
+ // FIXME: Is there some kind of AttrVisitor to use here?
+ switch (FromAttr->getKind()) {
+ case attr::Aligned: {
+ auto *From = cast<AlignedAttr>(FromAttr);
+ AlignedAttr *To;
+ auto CreateAlign = [&](bool IsAlignmentExpr, void *Alignment) {
+ return AlignedAttr::Create(ToContext, IsAlignmentExpr, Alignment, ToRange,
+ From->getSyntax(),
+ From->getSemanticSpelling());
+ };
+ if (From->isAlignmentExpr()) {
+ if (auto ToEOrErr = Import(From->getAlignmentExpr()))
+ To = CreateAlign(true, *ToEOrErr);
+ else
+ return ToEOrErr.takeError();
+ } else {
+ if (auto ToTOrErr = Import(From->getAlignmentType()))
+ To = CreateAlign(false, *ToTOrErr);
+ else
+ return ToTOrErr.takeError();
+ }
+ To->setInherited(From->isInherited());
+ To->setPackExpansion(From->isPackExpansion());
+ To->setImplicit(From->isImplicit());
+ ToAttr = To;
+ break;
+ }
+ default:
+ // FIXME: 'clone' copies every member but some of them should be imported.
+ // Handle other Attrs that have parameters that should be imported.
+ ToAttr = FromAttr->clone(ToContext);
+ ToAttr->setRange(ToRange);
+ break;
+ }
+ assert(ToAttr && "Attribute should be created.");
+
return ToAttr;
}
@@ -8241,7 +8193,7 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) {
// FIXME Should we remove these Decls from the LookupTable,
// and from ImportedFromDecls?
}
- SavedImportPaths[FromD].clear();
+ SavedImportPaths.erase(FromD);
// Do not return ToDOrErr, error was taken out of it.
return make_error<ImportError>(ErrOut);
@@ -8274,7 +8226,7 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) {
Imported(FromD, ToD);
updateFlags(FromD, ToD);
- SavedImportPaths[FromD].clear();
+ SavedImportPaths.erase(FromD);
return ToDOrErr;
}
@@ -8291,15 +8243,22 @@ Expected<DeclContext *> ASTImporter::ImportContext(DeclContext *FromDC) {
// need it to have a definition.
if (auto *ToRecord = dyn_cast<RecordDecl>(ToDC)) {
auto *FromRecord = cast<RecordDecl>(FromDC);
- if (ToRecord->isCompleteDefinition()) {
- // Do nothing.
- } else if (FromRecord->isCompleteDefinition()) {
+ if (ToRecord->isCompleteDefinition())
+ return ToDC;
+
+ // If FromRecord is not defined we need to force it to be.
+ // Simply calling CompleteDecl(...) for a RecordDecl will break some cases
+ // it will start the definition but we never finish it.
+ // If there are base classes they won't be imported and we will
+ // be missing anything that we inherit from those bases.
+ if (FromRecord->getASTContext().getExternalSource() &&
+ !FromRecord->isCompleteDefinition())
+ FromRecord->getASTContext().getExternalSource()->CompleteType(FromRecord);
+
+ if (FromRecord->isCompleteDefinition())
if (Error Err = ASTNodeImporter(*this).ImportDefinition(
FromRecord, ToRecord, ASTNodeImporter::IDK_Basic))
return std::move(Err);
- } else {
- CompleteDecl(ToRecord);
- }
} else if (auto *ToEnum = dyn_cast<EnumDecl>(ToDC)) {
auto *FromEnum = cast<EnumDecl>(FromDC);
if (ToEnum->isCompleteDefinition()) {
@@ -8366,11 +8325,7 @@ Expected<Stmt *> ASTImporter::Import(Stmt *FromS) {
// constructors.
ToE->setValueKind(FromE->getValueKind());
ToE->setObjectKind(FromE->getObjectKind());
- ToE->setTypeDependent(FromE->isTypeDependent());
- ToE->setValueDependent(FromE->isValueDependent());
- ToE->setInstantiationDependent(FromE->isInstantiationDependent());
- ToE->setContainsUnexpandedParameterPack(
- FromE->containsUnexpandedParameterPack());
+ ToE->setDependence(FromE->getDependence());
}
// Record the imported statement object.
@@ -8672,12 +8627,21 @@ Expected<FileID> ASTImporter::Import(FileID FromID, bool IsBuiltin) {
} else {
const SrcMgr::ContentCache *Cache = FromSLoc.getFile().getContentCache();
- if (!IsBuiltin) {
+ if (!IsBuiltin && !Cache->BufferOverridden) {
// Include location of this file.
ExpectedSLoc ToIncludeLoc = Import(FromSLoc.getFile().getIncludeLoc());
if (!ToIncludeLoc)
return ToIncludeLoc.takeError();
+ // Every FileID that is not the main FileID needs to have a valid include
+ // location so that the include chain points to the main FileID. When
+ // importing the main FileID (which has no include location), we need to
+ // create a fake include location in the main file to keep this property
+ // intact.
+ SourceLocation ToIncludeLocOrFakeLoc = *ToIncludeLoc;
+ if (FromID == FromSM.getMainFileID())
+ ToIncludeLocOrFakeLoc = ToSM.getLocForStartOfFile(ToSM.getMainFileID());
+
if (Cache->OrigEntry && Cache->OrigEntry->getDir()) {
// FIXME: We probably want to use getVirtualFile(), so we don't hit the
// disk again
@@ -8689,7 +8653,7 @@ Expected<FileID> ASTImporter::Import(FileID FromID, bool IsBuiltin) {
// point to a valid file and we get no Entry here. In this case try with
// the memory buffer below.
if (Entry)
- ToID = ToSM.createFileID(*Entry, *ToIncludeLoc,
+ ToID = ToSM.createFileID(*Entry, ToIncludeLocOrFakeLoc,
FromSLoc.getFile().getFileCharacteristic());
}
}
diff --git a/clang/lib/AST/ASTImporterLookupTable.cpp b/clang/lib/AST/ASTImporterLookupTable.cpp
index 7390329d4ed8d..4d6fff8f34191 100644
--- a/clang/lib/AST/ASTImporterLookupTable.cpp
+++ b/clang/lib/AST/ASTImporterLookupTable.cpp
@@ -45,7 +45,11 @@ struct Builder : RecursiveASTVisitor<Builder> {
LT.add(RTy->getAsCXXRecordDecl());
else if (const auto *SpecTy = dyn_cast<TemplateSpecializationType>(Ty))
LT.add(SpecTy->getAsCXXRecordDecl());
- else if (isa<TypedefType>(Ty)) {
+ else if (const auto *SubstTy =
+ dyn_cast<SubstTemplateTypeParmType>(Ty)) {
+ if (SubstTy->getAsCXXRecordDecl())
+ LT.add(SubstTy->getAsCXXRecordDecl());
+ } else if (isa<TypedefType>(Ty)) {
// We do not put friend typedefs to the lookup table because
// ASTImporter does not organize typedefs into redecl chains.
} else {
diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp
index db48405055cda..8b5b2444f1e25 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -31,10 +31,9 @@
// }
// ```
// Indeed, it has it's queue, which holds pairs of nodes, one from each graph,
-// this is the `DeclsToCheck` and it's pair is in `TentativeEquivalences`.
-// `TentativeEquivalences` also plays the role of the marking (`marked`)
-// functionality above, we use it to check whether we've already seen a pair of
-// nodes.
+// this is the `DeclsToCheck` member. `VisitedDecls` plays the role of the
+// marking (`marked`) functionality above, we use it to check whether we've
+// already seen a pair of nodes.
//
// We put in the elements into the queue only in the toplevel decl check
// function:
@@ -57,11 +56,6 @@
// doing. Thus, static implementation functions must not call the **member**
// functions.
//
-// So, now `TentativeEquivalences` plays two roles. It is used to store the
-// second half of the decls which we want to compare, plus it plays a role in
-// closing the recursion. On a long term, we could refactor structural
-// equivalency to be more alike to the traditional BFS.
-//
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTStructuralEquivalence.h"
@@ -623,6 +617,34 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
break;
}
+ case Type::DependentSizedMatrix: {
+ const DependentSizedMatrixType *Mat1 = cast<DependentSizedMatrixType>(T1);
+ const DependentSizedMatrixType *Mat2 = cast<DependentSizedMatrixType>(T2);
+ // The element types, row and column expressions must be structurally
+ // equivalent.
+ if (!IsStructurallyEquivalent(Context, Mat1->getRowExpr(),
+ Mat2->getRowExpr()) ||
+ !IsStructurallyEquivalent(Context, Mat1->getColumnExpr(),
+ Mat2->getColumnExpr()) ||
+ !IsStructurallyEquivalent(Context, Mat1->getElementType(),
+ Mat2->getElementType()))
+ return false;
+ break;
+ }
+
+ case Type::ConstantMatrix: {
+ const ConstantMatrixType *Mat1 = cast<ConstantMatrixType>(T1);
+ const ConstantMatrixType *Mat2 = cast<ConstantMatrixType>(T2);
+ // The element types must be structurally equivalent and the number of rows
+ // and columns must match.
+ if (!IsStructurallyEquivalent(Context, Mat1->getElementType(),
+ Mat2->getElementType()) ||
+ Mat1->getNumRows() != Mat2->getNumRows() ||
+ Mat1->getNumColumns() != Mat2->getNumColumns())
+ return false;
+ break;
+ }
+
case Type::FunctionProto: {
const auto *Proto1 = cast<FunctionProtoType>(T1);
const auto *Proto2 = cast<FunctionProtoType>(T2);
@@ -729,11 +751,31 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return false;
break;
- case Type::Auto:
- if (!IsStructurallyEquivalent(Context, cast<AutoType>(T1)->getDeducedType(),
- cast<AutoType>(T2)->getDeducedType()))
+ case Type::Auto: {
+ auto *Auto1 = cast<AutoType>(T1);
+ auto *Auto2 = cast<AutoType>(T2);
+ if (!IsStructurallyEquivalent(Context, Auto1->getDeducedType(),
+ Auto2->getDeducedType()))
return false;
+ if (Auto1->isConstrained() != Auto2->isConstrained())
+ return false;
+ if (Auto1->isConstrained()) {
+ if (Auto1->getTypeConstraintConcept() !=
+ Auto2->getTypeConstraintConcept())
+ return false;
+ ArrayRef<TemplateArgument> Auto1Args =
+ Auto1->getTypeConstraintArguments();
+ ArrayRef<TemplateArgument> Auto2Args =
+ Auto2->getTypeConstraintArguments();
+ if (Auto1Args.size() != Auto2Args.size())
+ return false;
+ for (unsigned I = 0, N = Auto1Args.size(); I != N; ++I) {
+ if (!IsStructurallyEquivalent(Context, Auto1Args[I], Auto2Args[I]))
+ return false;
+ }
+ }
break;
+ }
case Type::DeducedTemplateSpecialization: {
const auto *DT1 = cast<DeducedTemplateSpecializationType>(T1);
@@ -935,6 +977,24 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
cast<PipeType>(T2)->getElementType()))
return false;
break;
+ case Type::ExtInt: {
+ const auto *Int1 = cast<ExtIntType>(T1);
+ const auto *Int2 = cast<ExtIntType>(T2);
+
+ if (Int1->isUnsigned() != Int2->isUnsigned() ||
+ Int1->getNumBits() != Int2->getNumBits())
+ return false;
+ break;
+ }
+ case Type::DependentExtInt: {
+ const auto *Int1 = cast<DependentExtIntType>(T1);
+ const auto *Int2 = cast<DependentExtIntType>(T2);
+
+ if (Int1->isUnsigned() != Int2->isUnsigned() ||
+ !IsStructurallyEquivalent(Context, Int1->getNumBitsExpr(),
+ Int2->getNumBitsExpr()))
+ return false;
+ }
} // end switch
return true;
diff --git a/clang/lib/AST/ASTTypeTraits.cpp b/clang/lib/AST/ASTTypeTraits.cpp
index a5570c329ae80..34fc587694be9 100644
--- a/clang/lib/AST/ASTTypeTraits.cpp
+++ b/clang/lib/AST/ASTTypeTraits.cpp
@@ -18,8 +18,7 @@
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/OpenMPClause.h"
-namespace clang {
-namespace ast_type_traits {
+using namespace clang;
const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = {
{ NKI_None, "<None>" },
@@ -28,6 +27,7 @@ const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = {
{ NKI_None, "NestedNameSpecifierLoc" },
{ NKI_None, "QualType" },
{ NKI_None, "TypeLoc" },
+ { NKI_None, "CXXBaseSpecifier" },
{ NKI_None, "CXXCtorInitializer" },
{ NKI_None, "NestedNameSpecifier" },
{ NKI_None, "Decl" },
@@ -40,8 +40,8 @@ const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = {
#define TYPE(DERIVED, BASE) { NKI_##BASE, #DERIVED "Type" },
#include "clang/AST/TypeNodes.inc"
{ NKI_None, "OMPClause" },
-#define OPENMP_CLAUSE(TextualSpelling, Class) {NKI_OMPClause, #Class},
-#include "clang/Basic/OpenMPKinds.def"
+#define OMP_CLAUSE_CLASS(Enum, Str, Class) {NKI_OMPClause, #Class},
+#include "llvm/Frontend/OpenMP/OMPKinds.def"
};
bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const {
@@ -112,15 +112,15 @@ ASTNodeKind ASTNodeKind::getFromNode(const Type &T) {
ASTNodeKind ASTNodeKind::getFromNode(const OMPClause &C) {
switch (C.getClauseKind()) {
-#define OPENMP_CLAUSE(Name, Class) \
- case OMPC_##Name: return ASTNodeKind(NKI_##Class);
-#include "clang/Basic/OpenMPKinds.def"
- case OMPC_threadprivate:
- case OMPC_uniform:
- case OMPC_device_type:
- case OMPC_match:
- case OMPC_unknown:
+#define OMP_CLAUSE_CLASS(Enum, Str, Class) \
+ case llvm::omp::Clause::Enum: \
+ return ASTNodeKind(NKI_##Class);
+#define OMP_CLAUSE_NO_CLASS(Enum, Str) \
+ case llvm::omp::Clause::Enum: \
llvm_unreachable("unexpected OpenMP clause kind");
+ default:
+ break;
+#include "llvm/Frontend/OpenMP/OMPKinds.def"
}
llvm_unreachable("invalid stmt kind");
}
@@ -152,13 +152,14 @@ void DynTypedNode::print(llvm::raw_ostream &OS,
OS << "Unable to print values of type " << NodeKind.asStringRef() << "\n";
}
-void DynTypedNode::dump(llvm::raw_ostream &OS, SourceManager &SM) const {
+void DynTypedNode::dump(llvm::raw_ostream &OS,
+ const ASTContext &Context) const {
if (const Decl *D = get<Decl>())
D->dump(OS);
else if (const Stmt *S = get<Stmt>())
- S->dump(OS, SM);
+ S->dump(OS, Context);
else if (const Type *T = get<Type>())
- T->dump(OS);
+ T->dump(OS, Context);
else
OS << "Unable to dump values of type " << NodeKind.asStringRef() << "\n";
}
@@ -178,6 +179,3 @@ SourceRange DynTypedNode::getSourceRange() const {
return SourceRange(C->getBeginLoc(), C->getEndLoc());
return SourceRange();
}
-
-} // end namespace ast_type_traits
-} // end namespace clang
diff --git a/clang/lib/AST/AttrImpl.cpp b/clang/lib/AST/AttrImpl.cpp
index 0ef925ec1c901..7818fbb1918bb 100644
--- a/clang/lib/AST/AttrImpl.cpp
+++ b/clang/lib/AST/AttrImpl.cpp
@@ -16,4 +16,155 @@
#include "clang/AST/Type.h"
using namespace clang;
+void LoopHintAttr::printPrettyPragma(raw_ostream &OS,
+ const PrintingPolicy &Policy) const {
+ unsigned SpellingIndex = getAttributeSpellingListIndex();
+ // For "#pragma unroll" and "#pragma nounroll" the string "unroll" or
+ // "nounroll" is already emitted as the pragma name.
+ if (SpellingIndex == Pragma_nounroll ||
+ SpellingIndex == Pragma_nounroll_and_jam)
+ return;
+ else if (SpellingIndex == Pragma_unroll ||
+ SpellingIndex == Pragma_unroll_and_jam) {
+ OS << ' ' << getValueString(Policy);
+ return;
+ }
+
+ assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
+ OS << ' ' << getOptionName(option) << getValueString(Policy);
+}
+
+// Return a string containing the loop hint argument including the
+// enclosing parentheses.
+std::string LoopHintAttr::getValueString(const PrintingPolicy &Policy) const {
+ std::string ValueName;
+ llvm::raw_string_ostream OS(ValueName);
+ OS << "(";
+ if (state == Numeric)
+ value->printPretty(OS, nullptr, Policy);
+ else if (state == Enable)
+ OS << "enable";
+ else if (state == Full)
+ OS << "full";
+ else if (state == AssumeSafety)
+ OS << "assume_safety";
+ else
+ OS << "disable";
+ OS << ")";
+ return OS.str();
+}
+
+// Return a string suitable for identifying this attribute in diagnostics.
+std::string
+LoopHintAttr::getDiagnosticName(const PrintingPolicy &Policy) const {
+ unsigned SpellingIndex = getAttributeSpellingListIndex();
+ if (SpellingIndex == Pragma_nounroll)
+ return "#pragma nounroll";
+ else if (SpellingIndex == Pragma_unroll)
+ return "#pragma unroll" +
+ (option == UnrollCount ? getValueString(Policy) : "");
+ else if (SpellingIndex == Pragma_nounroll_and_jam)
+ return "#pragma nounroll_and_jam";
+ else if (SpellingIndex == Pragma_unroll_and_jam)
+ return "#pragma unroll_and_jam" +
+ (option == UnrollAndJamCount ? getValueString(Policy) : "");
+
+ assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
+ return getOptionName(option) + getValueString(Policy);
+}
+
+void OMPDeclareSimdDeclAttr::printPrettyPragma(
+ raw_ostream &OS, const PrintingPolicy &Policy) const {
+ if (getBranchState() != BS_Undefined)
+ OS << ' ' << ConvertBranchStateTyToStr(getBranchState());
+ if (auto *E = getSimdlen()) {
+ OS << " simdlen(";
+ E->printPretty(OS, nullptr, Policy);
+ OS << ")";
+ }
+ if (uniforms_size() > 0) {
+ OS << " uniform";
+ StringRef Sep = "(";
+ for (auto *E : uniforms()) {
+ OS << Sep;
+ E->printPretty(OS, nullptr, Policy);
+ Sep = ", ";
+ }
+ OS << ")";
+ }
+ alignments_iterator NI = alignments_begin();
+ for (auto *E : aligneds()) {
+ OS << " aligned(";
+ E->printPretty(OS, nullptr, Policy);
+ if (*NI) {
+ OS << ": ";
+ (*NI)->printPretty(OS, nullptr, Policy);
+ }
+ OS << ")";
+ ++NI;
+ }
+ steps_iterator I = steps_begin();
+ modifiers_iterator MI = modifiers_begin();
+ for (auto *E : linears()) {
+ OS << " linear(";
+ if (*MI != OMPC_LINEAR_unknown)
+ OS << getOpenMPSimpleClauseTypeName(llvm::omp::Clause::OMPC_linear, *MI)
+ << "(";
+ E->printPretty(OS, nullptr, Policy);
+ if (*MI != OMPC_LINEAR_unknown)
+ OS << ")";
+ if (*I) {
+ OS << ": ";
+ (*I)->printPretty(OS, nullptr, Policy);
+ }
+ OS << ")";
+ ++I;
+ ++MI;
+ }
+}
+
+void OMPDeclareTargetDeclAttr::printPrettyPragma(
+ raw_ostream &OS, const PrintingPolicy &Policy) const {
+ // Use fake syntax because it is for testing and debugging purpose only.
+ if (getDevType() != DT_Any)
+ OS << " device_type(" << ConvertDevTypeTyToStr(getDevType()) << ")";
+ if (getMapType() != MT_To)
+ OS << ' ' << ConvertMapTypeTyToStr(getMapType());
+}
+
+llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy>
+OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(const ValueDecl *VD) {
+ if (!VD->hasAttrs())
+ return llvm::None;
+ if (const auto *Attr = VD->getAttr<OMPDeclareTargetDeclAttr>())
+ return Attr->getMapType();
+
+ return llvm::None;
+}
+
+llvm::Optional<OMPDeclareTargetDeclAttr::DevTypeTy>
+OMPDeclareTargetDeclAttr::getDeviceType(const ValueDecl *VD) {
+ if (!VD->hasAttrs())
+ return llvm::None;
+ if (const auto *Attr = VD->getAttr<OMPDeclareTargetDeclAttr>())
+ return Attr->getDevType();
+
+ return llvm::None;
+}
+
+namespace clang {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const OMPTraitInfo &TI);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const OMPTraitInfo *TI);
+}
+
+void OMPDeclareVariantAttr::printPrettyPragma(
+ raw_ostream &OS, const PrintingPolicy &Policy) const {
+ if (const Expr *E = getVariantFuncRef()) {
+ OS << "(";
+ E->printPretty(OS, nullptr, Policy);
+ OS << ")";
+ }
+ OS << " match(" << traitInfos << ")";
+}
+
#include "clang/AST/AttrImpl.inc"
diff --git a/clang/lib/AST/CXXInheritance.cpp b/clang/lib/AST/CXXInheritance.cpp
index a3a3794b2edd4..8af97119e3cf9 100644
--- a/clang/lib/AST/CXXInheritance.cpp
+++ b/clang/lib/AST/CXXInheritance.cpp
@@ -147,37 +147,27 @@ CXXRecordDecl::isCurrentInstantiation(const DeclContext *CurContext) const {
return false;
}
-bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches,
- bool AllowShortCircuit) const {
+bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches) const {
SmallVector<const CXXRecordDecl*, 8> Queue;
const CXXRecordDecl *Record = this;
- bool AllMatches = true;
while (true) {
for (const auto &I : Record->bases()) {
const RecordType *Ty = I.getType()->getAs<RecordType>();
- if (!Ty) {
- if (AllowShortCircuit) return false;
- AllMatches = false;
- continue;
- }
+ if (!Ty)
+ return false;
CXXRecordDecl *Base =
cast_or_null<CXXRecordDecl>(Ty->getDecl()->getDefinition());
if (!Base ||
(Base->isDependentContext() &&
!Base->isCurrentInstantiation(Record))) {
- if (AllowShortCircuit) return false;
- AllMatches = false;
- continue;
+ return false;
}
Queue.push_back(Base);
- if (!BaseMatches(Base)) {
- if (AllowShortCircuit) return false;
- AllMatches = false;
- continue;
- }
+ if (!BaseMatches(Base))
+ return false;
}
if (Queue.empty())
@@ -185,7 +175,7 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches,
Record = Queue.pop_back_val(); // not actually a queue.
}
- return AllMatches;
+ return true;
}
bool CXXBasePaths::lookupInBases(ASTContext &Context,
@@ -758,6 +748,8 @@ CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const {
return false;
};
+ // FIXME: IsHidden reads from Overriding from the middle of a remove_if
+ // over the same sequence! Is this guaranteed to work?
Overriding.erase(
std::remove_if(Overriding.begin(), Overriding.end(), IsHidden),
Overriding.end());
diff --git a/clang/lib/AST/CommentCommandTraits.cpp b/clang/lib/AST/CommentCommandTraits.cpp
index b306fcbb154f3..bdc0dd47fb7d2 100644
--- a/clang/lib/AST/CommentCommandTraits.cpp
+++ b/clang/lib/AST/CommentCommandTraits.cpp
@@ -8,6 +8,7 @@
#include "clang/AST/CommentCommandTraits.h"
#include "llvm/ADT/STLExtras.h"
+#include <cassert>
namespace clang {
namespace comments {
diff --git a/clang/lib/AST/CommentSema.cpp b/clang/lib/AST/CommentSema.cpp
index 53c1832d1dd25..7642e73fa1714 100644
--- a/clang/lib/AST/CommentSema.cpp
+++ b/clang/lib/AST/CommentSema.cpp
@@ -12,6 +12,7 @@
#include "clang/AST/CommentDiagnostic.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/SmallString.h"
@@ -134,7 +135,9 @@ void Sema::checkContainerDeclVerbatimLine(const BlockCommandComment *Comment) {
unsigned DiagSelect;
switch (Comment->getCommandID()) {
case CommandTraits::KCI_class:
- DiagSelect = (!isClassOrStructDecl() && !isClassTemplateDecl()) ? 1 : 0;
+ DiagSelect =
+ (!isClassOrStructOrTagTypedefDecl() && !isClassTemplateDecl()) ? 1
+ : 0;
// Allow @class command on @interface declarations.
// FIXME. Currently, \class and @class are indistinguishable. So,
// \class is also allowed on an @interface declaration
@@ -148,7 +151,7 @@ void Sema::checkContainerDeclVerbatimLine(const BlockCommandComment *Comment) {
DiagSelect = !isObjCProtocolDecl() ? 3 : 0;
break;
case CommandTraits::KCI_struct:
- DiagSelect = !isClassOrStructDecl() ? 4 : 0;
+ DiagSelect = !isClassOrStructOrTagTypedefDecl() ? 4 : 0;
break;
case CommandTraits::KCI_union:
DiagSelect = !isUnionDecl() ? 5 : 0;
@@ -688,7 +691,7 @@ void Sema::checkDeprecatedCommand(const BlockCommandComment *Command) {
FD->doesThisDeclarationHaveABody())
return;
- const LangOptions &LO = FD->getASTContext().getLangOpts();
+ const LangOptions &LO = FD->getLangOpts();
const bool DoubleSquareBracket = LO.CPlusPlus14 || LO.C2x;
StringRef AttributeSpelling =
DoubleSquareBracket ? "[[deprecated]]" : "__attribute__((deprecated))";
@@ -935,15 +938,50 @@ bool Sema::isUnionDecl() {
return RD->isUnion();
return false;
}
+static bool isClassOrStructDeclImpl(const Decl *D) {
+ if (auto *record = dyn_cast_or_null<RecordDecl>(D))
+ return !record->isUnion();
+
+ return false;
+}
bool Sema::isClassOrStructDecl() {
if (!ThisDeclInfo)
return false;
if (!ThisDeclInfo->IsFilled)
inspectThisDecl();
- return ThisDeclInfo->CurrentDecl &&
- isa<RecordDecl>(ThisDeclInfo->CurrentDecl) &&
- !isUnionDecl();
+
+ if (!ThisDeclInfo->CurrentDecl)
+ return false;
+
+ return isClassOrStructDeclImpl(ThisDeclInfo->CurrentDecl);
+}
+
+bool Sema::isClassOrStructOrTagTypedefDecl() {
+ if (!ThisDeclInfo)
+ return false;
+ if (!ThisDeclInfo->IsFilled)
+ inspectThisDecl();
+
+ if (!ThisDeclInfo->CurrentDecl)
+ return false;
+
+ if (isClassOrStructDeclImpl(ThisDeclInfo->CurrentDecl))
+ return true;
+
+ if (auto *ThisTypedefDecl = dyn_cast<TypedefDecl>(ThisDeclInfo->CurrentDecl)) {
+ auto UnderlyingType = ThisTypedefDecl->getUnderlyingType();
+ if (auto ThisElaboratedType = dyn_cast<ElaboratedType>(UnderlyingType)) {
+ auto DesugaredType = ThisElaboratedType->desugar();
+ if (auto *DesugaredTypePtr = DesugaredType.getTypePtrOrNull()) {
+ if (auto *ThisRecordType = dyn_cast<RecordType>(DesugaredTypePtr)) {
+ return isClassOrStructDeclImpl(ThisRecordType->getAsRecordDecl());
+ }
+ }
+ }
+ }
+
+ return false;
}
bool Sema::isClassTemplateDecl() {
diff --git a/clang/lib/AST/ComparisonCategories.cpp b/clang/lib/AST/ComparisonCategories.cpp
index 07673230357f6..6b6826c02a123 100644
--- a/clang/lib/AST/ComparisonCategories.cpp
+++ b/clang/lib/AST/ComparisonCategories.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ComparisonCategories.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Type.h"
diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp
new file mode 100644
index 0000000000000..2333993dbeb40
--- /dev/null
+++ b/clang/lib/AST/ComputeDependence.cpp
@@ -0,0 +1,796 @@
+//===- ComputeDependence.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ComputeDependence.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/DependenceFlags.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprConcepts.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
+#include "clang/Basic/ExceptionSpecificationType.h"
+#include "llvm/ADT/ArrayRef.h"
+
+using namespace clang;
+
+ExprDependence clang::computeDependence(FullExpr *E) {
+ return E->getSubExpr()->getDependence();
+}
+
+ExprDependence clang::computeDependence(OpaqueValueExpr *E) {
+ auto D = toExprDependence(E->getType()->getDependence());
+ if (auto *S = E->getSourceExpr())
+ D |= S->getDependence();
+ assert(!(D & ExprDependence::UnexpandedPack));
+ return D;
+}
+
+ExprDependence clang::computeDependence(ParenExpr *E) {
+ return E->getSubExpr()->getDependence();
+}
+
+ExprDependence clang::computeDependence(UnaryOperator *E) {
+ return toExprDependence(E->getType()->getDependence()) |
+ E->getSubExpr()->getDependence();
+}
+
+ExprDependence clang::computeDependence(UnaryExprOrTypeTraitExpr *E) {
+ // Never type-dependent (C++ [temp.dep.expr]p3).
+ // Value-dependent if the argument is type-dependent.
+ if (E->isArgumentType())
+ return turnTypeToValueDependence(
+ toExprDependence(E->getArgumentType()->getDependence()));
+
+ auto ArgDeps = E->getArgumentExpr()->getDependence();
+ auto Deps = ArgDeps & ~ExprDependence::TypeValue;
+ // Value-dependent if the argument is type-dependent.
+ if (ArgDeps & ExprDependence::Type)
+ Deps |= ExprDependence::Value;
+ // Check to see if we are in the situation where alignof(decl) should be
+ // dependent because decl's alignment is dependent.
+ auto ExprKind = E->getKind();
+ if (ExprKind != UETT_AlignOf && ExprKind != UETT_PreferredAlignOf)
+ return Deps;
+ if ((Deps & ExprDependence::Value) && (Deps & ExprDependence::Instantiation))
+ return Deps;
+
+ auto *NoParens = E->getArgumentExpr()->IgnoreParens();
+ const ValueDecl *D = nullptr;
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(NoParens))
+ D = DRE->getDecl();
+ else if (const auto *ME = dyn_cast<MemberExpr>(NoParens))
+ D = ME->getMemberDecl();
+ if (!D)
+ return Deps;
+ for (const auto *I : D->specific_attrs<AlignedAttr>()) {
+ if (I->isAlignmentErrorDependent())
+ Deps |= ExprDependence::Error;
+ if (I->isAlignmentDependent())
+ Deps |= ExprDependence::ValueInstantiation;
+ }
+ return Deps;
+}
+
+ExprDependence clang::computeDependence(ArraySubscriptExpr *E) {
+ return E->getLHS()->getDependence() | E->getRHS()->getDependence();
+}
+
+ExprDependence clang::computeDependence(MatrixSubscriptExpr *E) {
+ return E->getBase()->getDependence() | E->getRowIdx()->getDependence() |
+ (E->getColumnIdx() ? E->getColumnIdx()->getDependence()
+ : ExprDependence::None);
+}
+
+ExprDependence clang::computeDependence(CompoundLiteralExpr *E) {
+ return toExprDependence(E->getTypeSourceInfo()->getType()->getDependence()) |
+ turnTypeToValueDependence(E->getInitializer()->getDependence());
+}
+
+ExprDependence clang::computeDependence(CastExpr *E) {
+ // Cast expressions are type-dependent if the type is
+ // dependent (C++ [temp.dep.expr]p3).
+ // Cast expressions are value-dependent if the type is
+ // dependent or if the subexpression is value-dependent.
+ auto D = toExprDependence(E->getType()->getDependence());
+ if (E->getStmtClass() == Stmt::ImplicitCastExprClass) {
+ // An implicit cast expression doesn't (lexically) contain an
+ // unexpanded pack, even if its target type does.
+ D &= ~ExprDependence::UnexpandedPack;
+ }
+ if (auto *S = E->getSubExpr())
+ D |= S->getDependence() & ~ExprDependence::Type;
+ return D;
+}
+
+ExprDependence clang::computeDependence(BinaryOperator *E) {
+ return E->getLHS()->getDependence() | E->getRHS()->getDependence();
+}
+
+ExprDependence clang::computeDependence(ConditionalOperator *E) {
+ // The type of the conditional operator depends on the type of the conditional
+ // to support the GCC vector conditional extension. Additionally,
+ // [temp.dep.expr] does specify state that this should be dependent on ALL sub
+ // expressions.
+ return E->getCond()->getDependence() | E->getLHS()->getDependence() |
+ E->getRHS()->getDependence();
+}
+
+ExprDependence clang::computeDependence(BinaryConditionalOperator *E) {
+ return E->getCommon()->getDependence() | E->getFalseExpr()->getDependence();
+}
+
+ExprDependence clang::computeDependence(StmtExpr *E, unsigned TemplateDepth) {
+ auto D = toExprDependence(E->getType()->getDependence());
+ // Propagate dependence of the result.
+ if (const auto *CompoundExprResult =
+ dyn_cast_or_null<ValueStmt>(E->getSubStmt()->getStmtExprResult()))
+ if (const Expr *ResultExpr = CompoundExprResult->getExprStmt())
+ D |= ResultExpr->getDependence();
+ // Note: we treat a statement-expression in a dependent context as always
+ // being value- and instantiation-dependent. This matches the behavior of
+ // lambda-expressions and GCC.
+ if (TemplateDepth)
+ D |= ExprDependence::ValueInstantiation;
+ // A param pack cannot be expanded over stmtexpr boundaries.
+ return D & ~ExprDependence::UnexpandedPack;
+}
+
+ExprDependence clang::computeDependence(ConvertVectorExpr *E) {
+ auto D = toExprDependence(E->getType()->getDependence()) |
+ E->getSrcExpr()->getDependence();
+ if (!E->getType()->isDependentType())
+ D &= ~ExprDependence::Type;
+ return D;
+}
+
+ExprDependence clang::computeDependence(ChooseExpr *E) {
+ if (E->isConditionDependent())
+ return ExprDependence::TypeValueInstantiation |
+ E->getCond()->getDependence() | E->getLHS()->getDependence() |
+ E->getRHS()->getDependence();
+
+ auto Cond = E->getCond()->getDependence();
+ auto Active = E->getLHS()->getDependence();
+ auto Inactive = E->getRHS()->getDependence();
+ if (!E->isConditionTrue())
+ std::swap(Active, Inactive);
+ // Take type- and value- dependency from the active branch. Propagate all
+ // other flags from all branches.
+ return (Active & ExprDependence::TypeValue) |
+ ((Cond | Active | Inactive) & ~ExprDependence::TypeValue);
+}
+
+ExprDependence clang::computeDependence(ParenListExpr *P) {
+ auto D = ExprDependence::None;
+ for (auto *E : P->exprs())
+ D |= E->getDependence();
+ return D;
+}
+
+ExprDependence clang::computeDependence(VAArgExpr *E) {
+ auto D =
+ toExprDependence(E->getWrittenTypeInfo()->getType()->getDependence()) |
+ (E->getSubExpr()->getDependence() & ~ExprDependence::Type);
+ return D & ~ExprDependence::Value;
+}
+
+ExprDependence clang::computeDependence(NoInitExpr *E) {
+ return toExprDependence(E->getType()->getDependence()) &
+ (ExprDependence::Instantiation | ExprDependence::Error);
+}
+
+ExprDependence clang::computeDependence(ArrayInitLoopExpr *E) {
+ auto D = E->getCommonExpr()->getDependence() |
+ E->getSubExpr()->getDependence() | ExprDependence::Instantiation;
+ if (!E->getType()->isInstantiationDependentType())
+ D &= ~ExprDependence::Instantiation;
+ return turnTypeToValueDependence(D);
+}
+
+ExprDependence clang::computeDependence(ImplicitValueInitExpr *E) {
+ return toExprDependence(E->getType()->getDependence()) &
+ ExprDependence::Instantiation;
+}
+
+ExprDependence clang::computeDependence(ExtVectorElementExpr *E) {
+ return E->getBase()->getDependence();
+}
+
+ExprDependence clang::computeDependence(BlockExpr *E) {
+ auto D = toExprDependence(E->getType()->getDependence());
+ if (E->getBlockDecl()->isDependentContext())
+ D |= ExprDependence::Instantiation;
+ return D & ~ExprDependence::UnexpandedPack;
+}
+
+ExprDependence clang::computeDependence(AsTypeExpr *E) {
+ auto D = toExprDependence(E->getType()->getDependence()) |
+ E->getSrcExpr()->getDependence();
+ if (!E->getType()->isDependentType())
+ D &= ~ExprDependence::Type;
+ return D;
+}
+
+ExprDependence clang::computeDependence(CXXRewrittenBinaryOperator *E) {
+ return E->getSemanticForm()->getDependence();
+}
+
+ExprDependence clang::computeDependence(CXXStdInitializerListExpr *E) {
+ auto D = turnTypeToValueDependence(E->getSubExpr()->getDependence());
+ D |= toExprDependence(E->getType()->getDependence()) &
+ (ExprDependence::Type | ExprDependence::Error);
+ return D;
+}
+
+ExprDependence clang::computeDependence(CXXTypeidExpr *E) {
+ auto D = ExprDependence::None;
+ if (E->isTypeOperand())
+ D = toExprDependence(
+ E->getTypeOperandSourceInfo()->getType()->getDependence());
+ else
+ D = turnTypeToValueDependence(E->getExprOperand()->getDependence());
+ // typeid is never type-dependent (C++ [temp.dep.expr]p4)
+ return D & ~ExprDependence::Type;
+}
+
+ExprDependence clang::computeDependence(MSPropertyRefExpr *E) {
+ return E->getBaseExpr()->getDependence() & ~ExprDependence::Type;
+}
+
+ExprDependence clang::computeDependence(MSPropertySubscriptExpr *E) {
+ return E->getIdx()->getDependence();
+}
+
+ExprDependence clang::computeDependence(CXXUuidofExpr *E) {
+ if (E->isTypeOperand())
+ return turnTypeToValueDependence(toExprDependence(
+ E->getTypeOperandSourceInfo()->getType()->getDependence()));
+
+ return turnTypeToValueDependence(E->getExprOperand()->getDependence());
+}
+
+ExprDependence clang::computeDependence(CXXThisExpr *E) {
+ // 'this' is type-dependent if the class type of the enclosing
+ // member function is dependent (C++ [temp.dep.expr]p2)
+ auto D = toExprDependence(E->getType()->getDependence());
+ assert(!(D & ExprDependence::UnexpandedPack));
+ return D;
+}
+
+ExprDependence clang::computeDependence(CXXThrowExpr *E) {
+ auto *Op = E->getSubExpr();
+ if (!Op)
+ return ExprDependence::None;
+ return Op->getDependence() & ~ExprDependence::TypeValue;
+}
+
+ExprDependence clang::computeDependence(CXXBindTemporaryExpr *E) {
+ return E->getSubExpr()->getDependence();
+}
+
+ExprDependence clang::computeDependence(CXXScalarValueInitExpr *E) {
+ return toExprDependence(E->getType()->getDependence()) &
+ ~ExprDependence::TypeValue;
+}
+
+ExprDependence clang::computeDependence(CXXDeleteExpr *E) {
+ return turnTypeToValueDependence(E->getArgument()->getDependence());
+}
+
+ExprDependence clang::computeDependence(ArrayTypeTraitExpr *E) {
+ auto D = toExprDependence(E->getQueriedType()->getDependence());
+ if (auto *Dim = E->getDimensionExpression())
+ D |= Dim->getDependence();
+ return turnTypeToValueDependence(D);
+}
+
+ExprDependence clang::computeDependence(ExpressionTraitExpr *E) {
+ // Never type-dependent.
+ auto D = E->getQueriedExpression()->getDependence() & ~ExprDependence::Type;
+ // Value-dependent if the argument is type-dependent.
+ if (E->getQueriedExpression()->isTypeDependent())
+ D |= ExprDependence::Value;
+ return D;
+}
+
+ExprDependence clang::computeDependence(CXXNoexceptExpr *E, CanThrowResult CT) {
+ auto D = E->getOperand()->getDependence() & ~ExprDependence::TypeValue;
+ if (CT == CT_Dependent)
+ D |= ExprDependence::ValueInstantiation;
+ return D;
+}
+
+ExprDependence clang::computeDependence(PackExpansionExpr *E) {
+ return (E->getPattern()->getDependence() & ~ExprDependence::UnexpandedPack) |
+ ExprDependence::TypeValueInstantiation;
+}
+
+ExprDependence clang::computeDependence(SubstNonTypeTemplateParmExpr *E) {
+ return E->getReplacement()->getDependence();
+}
+
+ExprDependence clang::computeDependence(CoroutineSuspendExpr *E) {
+ if (auto *Resume = E->getResumeExpr())
+ return (Resume->getDependence() &
+ (ExprDependence::TypeValue | ExprDependence::Error)) |
+ (E->getCommonExpr()->getDependence() & ~ExprDependence::TypeValue);
+ return E->getCommonExpr()->getDependence() |
+ ExprDependence::TypeValueInstantiation;
+}
+
+ExprDependence clang::computeDependence(DependentCoawaitExpr *E) {
+ return E->getOperand()->getDependence() |
+ ExprDependence::TypeValueInstantiation;
+}
+
+ExprDependence clang::computeDependence(ObjCBoxedExpr *E) {
+ return E->getSubExpr()->getDependence();
+}
+
+ExprDependence clang::computeDependence(ObjCEncodeExpr *E) {
+ return toExprDependence(E->getEncodedType()->getDependence());
+}
+
+ExprDependence clang::computeDependence(ObjCIvarRefExpr *E) {
+ return turnTypeToValueDependence(E->getBase()->getDependence());
+}
+
+ExprDependence clang::computeDependence(ObjCPropertyRefExpr *E) {
+ if (E->isObjectReceiver())
+ return E->getBase()->getDependence() & ~ExprDependence::Type;
+ if (E->isSuperReceiver())
+ return toExprDependence(E->getSuperReceiverType()->getDependence()) &
+ ~ExprDependence::TypeValue;
+ assert(E->isClassReceiver());
+ return ExprDependence::None;
+}
+
+ExprDependence clang::computeDependence(ObjCSubscriptRefExpr *E) {
+ return E->getBaseExpr()->getDependence() | E->getKeyExpr()->getDependence();
+}
+
+ExprDependence clang::computeDependence(ObjCIsaExpr *E) {
+ return E->getBase()->getDependence() & ~ExprDependence::Type &
+ ~ExprDependence::UnexpandedPack;
+}
+
+ExprDependence clang::computeDependence(ObjCIndirectCopyRestoreExpr *E) {
+ return E->getSubExpr()->getDependence();
+}
+
+ExprDependence clang::computeDependence(OMPArraySectionExpr *E) {
+ auto D = E->getBase()->getDependence();
+ if (auto *LB = E->getLowerBound())
+ D |= LB->getDependence();
+ if (auto *Len = E->getLength())
+ D |= Len->getDependence();
+ return D;
+}
+
+ExprDependence clang::computeDependence(OMPArrayShapingExpr *E) {
+ auto D = E->getBase()->getDependence() |
+ toExprDependence(E->getType()->getDependence());
+ for (Expr *Dim: E->getDimensions())
+ if (Dim)
+ D |= Dim->getDependence();
+ return D;
+}
+
+ExprDependence clang::computeDependence(OMPIteratorExpr *E) {
+ auto D = toExprDependence(E->getType()->getDependence());
+ for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) {
+ if (auto *VD = cast_or_null<ValueDecl>(E->getIteratorDecl(I)))
+ D |= toExprDependence(VD->getType()->getDependence());
+ OMPIteratorExpr::IteratorRange IR = E->getIteratorRange(I);
+ if (Expr *BE = IR.Begin)
+ D |= BE->getDependence();
+ if (Expr *EE = IR.End)
+ D |= EE->getDependence();
+ if (Expr *SE = IR.Step)
+ D |= SE->getDependence();
+ }
+ return D;
+}
+
+/// Compute the type-, value-, and instantiation-dependence of a
+/// declaration reference
+/// based on the declaration being referenced.
+ExprDependence clang::computeDependence(DeclRefExpr *E, const ASTContext &Ctx) {
+ auto Deps = ExprDependence::None;
+
+ if (auto *NNS = E->getQualifier())
+ Deps |= toExprDependence(NNS->getDependence() &
+ ~NestedNameSpecifierDependence::Dependent);
+
+ if (auto *FirstArg = E->getTemplateArgs()) {
+ unsigned NumArgs = E->getNumTemplateArgs();
+ for (auto *Arg = FirstArg, *End = FirstArg + NumArgs; Arg < End; ++Arg)
+ Deps |= toExprDependence(Arg->getArgument().getDependence());
+ }
+
+ auto *Decl = E->getDecl();
+ auto Type = E->getType();
+
+ if (Decl->isParameterPack())
+ Deps |= ExprDependence::UnexpandedPack;
+ Deps |= toExprDependence(Type->getDependence()) & ExprDependence::Error;
+
+ // (TD) C++ [temp.dep.expr]p3:
+ // An id-expression is type-dependent if it contains:
+ //
+ // and
+ //
+ // (VD) C++ [temp.dep.constexpr]p2:
+ // An identifier is value-dependent if it is:
+
+ // (TD) - an identifier that was declared with dependent type
+ // (VD) - a name declared with a dependent type,
+ if (Type->isDependentType())
+ return Deps | ExprDependence::TypeValueInstantiation;
+ else if (Type->isInstantiationDependentType())
+ Deps |= ExprDependence::Instantiation;
+
+ // (TD) - a conversion-function-id that specifies a dependent type
+ if (Decl->getDeclName().getNameKind() ==
+ DeclarationName::CXXConversionFunctionName) {
+ QualType T = Decl->getDeclName().getCXXNameType();
+ if (T->isDependentType())
+ return Deps | ExprDependence::TypeValueInstantiation;
+
+ if (T->isInstantiationDependentType())
+ Deps |= ExprDependence::Instantiation;
+ }
+
+ // (VD) - the name of a non-type template parameter,
+ if (isa<NonTypeTemplateParmDecl>(Decl))
+ return Deps | ExprDependence::ValueInstantiation;
+
+ // (VD) - a constant with integral or enumeration type and is
+ // initialized with an expression that is value-dependent.
+ // (VD) - a constant with literal type and is initialized with an
+ // expression that is value-dependent [C++11].
+ // (VD) - FIXME: Missing from the standard:
+ // - an entity with reference type and is initialized with an
+ // expression that is value-dependent [C++11]
+ if (VarDecl *Var = dyn_cast<VarDecl>(Decl)) {
+ if ((Ctx.getLangOpts().CPlusPlus11
+ ? Var->getType()->isLiteralType(Ctx)
+ : Var->getType()->isIntegralOrEnumerationType()) &&
+ (Var->getType().isConstQualified() ||
+ Var->getType()->isReferenceType())) {
+ if (const Expr *Init = Var->getAnyInitializer())
+ if (Init->isValueDependent()) {
+ Deps |= ExprDependence::ValueInstantiation;
+ }
+ }
+
+ // (VD) - FIXME: Missing from the standard:
+ // - a member function or a static data member of the current
+ // instantiation
+ if (Var->isStaticDataMember() &&
+ Var->getDeclContext()->isDependentContext()) {
+ Deps |= ExprDependence::ValueInstantiation;
+ TypeSourceInfo *TInfo = Var->getFirstDecl()->getTypeSourceInfo();
+ if (TInfo->getType()->isIncompleteArrayType())
+ Deps |= ExprDependence::Type;
+ }
+
+ return Deps;
+ }
+
+ // (VD) - FIXME: Missing from the standard:
+ // - a member function or a static data member of the current
+ // instantiation
+ if (isa<CXXMethodDecl>(Decl) && Decl->getDeclContext()->isDependentContext())
+ Deps |= ExprDependence::ValueInstantiation;
+ return Deps;
+}
+
+ExprDependence clang::computeDependence(RecoveryExpr *E) {
+ // RecoveryExpr is
+ // - always value-dependent, and therefore instantiation dependent
+ // - contains errors (ExprDependence::Error), by definition
+ // - type-dependent if we don't know the type (fallback to an opaque
+ // dependent type), or the type is known and dependent, or it has
+ // type-dependent subexpressions.
+ auto D = toExprDependence(E->getType()->getDependence()) |
+ ExprDependence::ValueInstantiation | ExprDependence::Error;
+ // FIXME: remove the type-dependent bit from subexpressions, if the
+ // RecoveryExpr has a non-dependent type.
+ for (auto *S : E->subExpressions())
+ D |= S->getDependence();
+ return D;
+}
+
+ExprDependence clang::computeDependence(PredefinedExpr *E) {
+ return toExprDependence(E->getType()->getDependence()) &
+ ~ExprDependence::UnexpandedPack;
+}
+
+ExprDependence clang::computeDependence(CallExpr *E,
+ llvm::ArrayRef<Expr *> PreArgs) {
+ auto D = E->getCallee()->getDependence();
+ for (auto *A : llvm::makeArrayRef(E->getArgs(), E->getNumArgs())) {
+ if (A)
+ D |= A->getDependence();
+ }
+ for (auto *A : PreArgs)
+ D |= A->getDependence();
+ return D;
+}
+
+ExprDependence clang::computeDependence(OffsetOfExpr *E) {
+ auto D = turnTypeToValueDependence(
+ toExprDependence(E->getTypeSourceInfo()->getType()->getDependence()));
+ for (unsigned I = 0, N = E->getNumExpressions(); I < N; ++I)
+ D |= turnTypeToValueDependence(E->getIndexExpr(I)->getDependence());
+ return D;
+}
+
+ExprDependence clang::computeDependence(MemberExpr *E) {
+ auto *MemberDecl = E->getMemberDecl();
+ auto D = E->getBase()->getDependence();
+ if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) {
+ DeclContext *DC = MemberDecl->getDeclContext();
+ // dyn_cast_or_null is used to handle objC variables which do not
+ // have a declaration context.
+ CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(DC);
+ if (RD && RD->isDependentContext() && RD->isCurrentInstantiation(DC)) {
+ if (!E->getType()->isDependentType())
+ D &= ~ExprDependence::Type;
+ }
+
+ // Bitfield with value-dependent width is type-dependent.
+ if (FD && FD->isBitField() && FD->getBitWidth()->isValueDependent()) {
+ D |= ExprDependence::Type;
+ }
+ }
+ // FIXME: move remaining dependence computation from MemberExpr::Create()
+ return D;
+}
+
+ExprDependence clang::computeDependence(InitListExpr *E) {
+ auto D = ExprDependence::None;
+ for (auto *A : E->inits())
+ D |= A->getDependence();
+ return D;
+}
+
+ExprDependence clang::computeDependence(ShuffleVectorExpr *E) {
+ auto D = toExprDependence(E->getType()->getDependence());
+ for (auto *C : llvm::makeArrayRef(E->getSubExprs(), E->getNumSubExprs()))
+ D |= C->getDependence();
+ return D;
+}
+
+ExprDependence clang::computeDependence(GenericSelectionExpr *E,
+ bool ContainsUnexpandedPack) {
+ auto D = ContainsUnexpandedPack ? ExprDependence::UnexpandedPack
+ : ExprDependence::None;
+ for (auto *AE : E->getAssocExprs())
+ D |= AE->getDependence() & ExprDependence::Error;
+ D |= E->getControllingExpr()->getDependence() & ExprDependence::Error;
+
+ if (E->isResultDependent())
+ return D | ExprDependence::TypeValueInstantiation;
+ return D | (E->getResultExpr()->getDependence() &
+ ~ExprDependence::UnexpandedPack);
+}
+
+ExprDependence clang::computeDependence(DesignatedInitExpr *E) {
+ auto Deps = E->getInit()->getDependence();
+ for (auto D : E->designators()) {
+ auto DesignatorDeps = ExprDependence::None;
+ if (D.isArrayDesignator())
+ DesignatorDeps |= E->getArrayIndex(D)->getDependence();
+ else if (D.isArrayRangeDesignator())
+ DesignatorDeps |= E->getArrayRangeStart(D)->getDependence() |
+ E->getArrayRangeEnd(D)->getDependence();
+ Deps |= DesignatorDeps;
+ if (DesignatorDeps & ExprDependence::TypeValue)
+ Deps |= ExprDependence::TypeValueInstantiation;
+ }
+ return Deps;
+}
+
+ExprDependence clang::computeDependence(PseudoObjectExpr *O) {
+ auto D = O->getSyntacticForm()->getDependence();
+ for (auto *E : O->semantics())
+ D |= E->getDependence();
+ return D;
+}
+
+ExprDependence clang::computeDependence(AtomicExpr *A) {
+ auto D = ExprDependence::None;
+ for (auto *E : llvm::makeArrayRef(A->getSubExprs(), A->getNumSubExprs()))
+ D |= E->getDependence();
+ return D;
+}
+
+ExprDependence clang::computeDependence(CXXNewExpr *E) {
+ auto D = toExprDependence(E->getType()->getDependence());
+ auto Size = E->getArraySize();
+ if (Size.hasValue() && *Size)
+ D |= turnTypeToValueDependence((*Size)->getDependence());
+ if (auto *I = E->getInitializer())
+ D |= turnTypeToValueDependence(I->getDependence());
+ for (auto *A : E->placement_arguments())
+ D |= turnTypeToValueDependence(A->getDependence());
+ return D;
+}
+
+ExprDependence clang::computeDependence(CXXPseudoDestructorExpr *E) {
+ auto D = E->getBase()->getDependence();
+ if (!E->getDestroyedType().isNull())
+ D |= toExprDependence(E->getDestroyedType()->getDependence());
+ if (auto *ST = E->getScopeTypeInfo())
+ D |= turnTypeToValueDependence(
+ toExprDependence(ST->getType()->getDependence()));
+ if (auto *Q = E->getQualifier())
+ D |= toExprDependence(Q->getDependence() &
+ ~NestedNameSpecifierDependence::Dependent);
+ return D;
+}
+
+static inline ExprDependence getDependenceInExpr(DeclarationNameInfo Name) {
+ auto D = ExprDependence::None;
+ if (Name.isInstantiationDependent())
+ D |= ExprDependence::Instantiation;
+ if (Name.containsUnexpandedParameterPack())
+ D |= ExprDependence::UnexpandedPack;
+ return D;
+}
+
+ExprDependence
+clang::computeDependence(OverloadExpr *E, bool KnownDependent,
+ bool KnownInstantiationDependent,
+ bool KnownContainsUnexpandedParameterPack) {
+ auto Deps = ExprDependence::None;
+ if (KnownDependent)
+ Deps |= ExprDependence::TypeValue;
+ if (KnownInstantiationDependent)
+ Deps |= ExprDependence::Instantiation;
+ if (KnownContainsUnexpandedParameterPack)
+ Deps |= ExprDependence::UnexpandedPack;
+ Deps |= getDependenceInExpr(E->getNameInfo());
+ if (auto *Q = E->getQualifier())
+ Deps |= toExprDependence(Q->getDependence() &
+ ~NestedNameSpecifierDependence::Dependent);
+ for (auto *D : E->decls()) {
+ if (D->getDeclContext()->isDependentContext() ||
+ isa<UnresolvedUsingValueDecl>(D))
+ Deps |= ExprDependence::TypeValueInstantiation;
+ }
+ // If we have explicit template arguments, check for dependent
+ // template arguments and whether they contain any unexpanded pack
+ // expansions.
+ for (auto A : E->template_arguments())
+ Deps |= toExprDependence(A.getArgument().getDependence());
+ return Deps;
+}
+
+ExprDependence clang::computeDependence(DependentScopeDeclRefExpr *E) {
+ auto D = ExprDependence::TypeValue;
+ D |= getDependenceInExpr(E->getNameInfo());
+ if (auto *Q = E->getQualifier())
+ D |= toExprDependence(Q->getDependence());
+ for (auto A : E->template_arguments())
+ D |= toExprDependence(A.getArgument().getDependence());
+ return D;
+}
+
+ExprDependence clang::computeDependence(CXXConstructExpr *E) {
+ auto D = toExprDependence(E->getType()->getDependence());
+ for (auto *A : E->arguments())
+ D |= A->getDependence() & ~ExprDependence::Type;
+ return D;
+}
+
+ExprDependence clang::computeDependence(LambdaExpr *E,
+ bool ContainsUnexpandedParameterPack) {
+ auto D = toExprDependence(E->getType()->getDependence());
+ if (ContainsUnexpandedParameterPack)
+ D |= ExprDependence::UnexpandedPack;
+ return D;
+}
+
+ExprDependence clang::computeDependence(CXXUnresolvedConstructExpr *E) {
+ auto D = ExprDependence::ValueInstantiation;
+ D |= toExprDependence(E->getType()->getDependence());
+ if (E->getType()->getContainedDeducedType())
+ D |= ExprDependence::Type;
+ for (auto *A : E->arguments())
+ D |= A->getDependence() &
+ (ExprDependence::UnexpandedPack | ExprDependence::Error);
+ return D;
+}
+
+ExprDependence clang::computeDependence(CXXDependentScopeMemberExpr *E) {
+ auto D = ExprDependence::TypeValueInstantiation;
+ if (!E->isImplicitAccess())
+ D |= E->getBase()->getDependence();
+ if (auto *Q = E->getQualifier())
+ D |= toExprDependence(Q->getDependence());
+ D |= getDependenceInExpr(E->getMemberNameInfo());
+ for (auto A : E->template_arguments())
+ D |= toExprDependence(A.getArgument().getDependence());
+ return D;
+}
+
+ExprDependence clang::computeDependence(MaterializeTemporaryExpr *E) {
+ return E->getSubExpr()->getDependence();
+}
+
+ExprDependence clang::computeDependence(CXXFoldExpr *E) {
+ auto D = ExprDependence::TypeValueInstantiation;
+ for (const auto *C : {E->getLHS(), E->getRHS()}) {
+ if (C)
+ D |= C->getDependence() & ~ExprDependence::UnexpandedPack;
+ }
+ return D;
+}
+
+ExprDependence clang::computeDependence(TypeTraitExpr *E) {
+ auto D = ExprDependence::None;
+ for (const auto *A : E->getArgs())
+ D |=
+ toExprDependence(A->getType()->getDependence()) & ~ExprDependence::Type;
+ return D;
+}
+
+ExprDependence clang::computeDependence(ConceptSpecializationExpr *E,
+ bool ValueDependent) {
+ auto TA = TemplateArgumentDependence::None;
+ const auto InterestingDeps = TemplateArgumentDependence::Instantiation |
+ TemplateArgumentDependence::UnexpandedPack;
+ for (const TemplateArgumentLoc &ArgLoc :
+ E->getTemplateArgsAsWritten()->arguments()) {
+ TA |= ArgLoc.getArgument().getDependence() & InterestingDeps;
+ if (TA == InterestingDeps)
+ break;
+ }
+
+ ExprDependence D =
+ ValueDependent ? ExprDependence::Value : ExprDependence::None;
+ return D | toExprDependence(TA);
+}
+
+ExprDependence clang::computeDependence(ObjCArrayLiteral *E) {
+ auto D = ExprDependence::None;
+ Expr **Elements = E->getElements();
+ for (unsigned I = 0, N = E->getNumElements(); I != N; ++I)
+ D |= turnTypeToValueDependence(Elements[I]->getDependence());
+ return D;
+}
+
+ExprDependence clang::computeDependence(ObjCDictionaryLiteral *E) {
+ auto Deps = ExprDependence::None;
+ for (unsigned I = 0, N = E->getNumElements(); I < N; ++I) {
+ auto KV = E->getKeyValueElement(I);
+ auto KVDeps = turnTypeToValueDependence(KV.Key->getDependence() |
+ KV.Value->getDependence());
+ if (KV.EllipsisLoc.isValid())
+ KVDeps &= ~ExprDependence::UnexpandedPack;
+ Deps |= KVDeps;
+ }
+ return Deps;
+}
+
+ExprDependence clang::computeDependence(ObjCMessageExpr *E) {
+ auto D = ExprDependence::None;
+ if (auto *R = E->getInstanceReceiver())
+ D |= R->getDependence();
+ else
+ D |= toExprDependence(E->getType()->getDependence());
+ for (auto *A : E->arguments())
+ D |= A->getDependence();
+ return D;
+}
diff --git a/clang/lib/AST/DataCollection.cpp b/clang/lib/AST/DataCollection.cpp
index 8e67c101dee1f..d3f2c22e9cc3a 100644
--- a/clang/lib/AST/DataCollection.cpp
+++ b/clang/lib/AST/DataCollection.cpp
@@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/DataCollection.h"
-
+#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
namespace clang {
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 0d30f64b992e0..5c0a98815dd79 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -892,6 +892,10 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
if (!TD->getAnonDeclWithTypedefName(/*AnyRedecl*/true))
return LinkageInfo::none();
+ } else if (isa<MSGuidDecl>(D)) {
+ // A GUID behaves like an inline variable with external linkage. Fall
+ // through.
+
// Everything not covered here has no linkage.
} else {
return LinkageInfo::none();
@@ -1318,19 +1322,6 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
LV.isVisibilityExplicit());
}
-static inline const CXXRecordDecl*
-getOutermostEnclosingLambda(const CXXRecordDecl *Record) {
- const CXXRecordDecl *Ret = Record;
- while (Record && Record->isLambda()) {
- Ret = Record;
- if (!Record->getParent()) break;
- // Get the Containing Class of this Lambda Class
- Record = dyn_cast_or_null<CXXRecordDecl>(
- Record->getParent()->getParent());
- }
- return Ret;
-}
-
LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D,
LVComputationKind computation,
bool IgnoreVarTypeLinkage) {
@@ -1396,25 +1387,9 @@ LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D,
return getInternalLinkageFor(D);
}
- // This lambda has its linkage/visibility determined:
- // - either by the outermost lambda if that lambda has no mangling
- // number.
- // - or by the parent of the outer most lambda
- // This prevents infinite recursion in settings such as nested lambdas
- // used in NSDMI's, for e.g.
- // struct L {
- // int t{};
- // int t2 = ([](int a) { return [](int b) { return b; };})(t)(t);
- // };
- const CXXRecordDecl *OuterMostLambda =
- getOutermostEnclosingLambda(Record);
- if (OuterMostLambda->hasKnownLambdaInternalLinkage() ||
- !OuterMostLambda->getLambdaManglingNumber())
- return getInternalLinkageFor(D);
-
return getLVForClosure(
- OuterMostLambda->getDeclContext()->getRedeclContext(),
- OuterMostLambda->getLambdaContextDecl(), computation);
+ Record->getDeclContext()->getRedeclContext(),
+ Record->getLambdaContextDecl(), computation);
}
break;
@@ -1571,10 +1546,19 @@ void NamedDecl::printQualifiedName(raw_ostream &OS,
return;
}
printNestedNameSpecifier(OS, P);
- if (getDeclName() || isa<DecompositionDecl>(this))
+ if (getDeclName())
OS << *this;
- else
- OS << "(anonymous)";
+ else {
+ // Give the printName override a chance to pick a different name before we
+ // fall back to "(anonymous)".
+ SmallString<64> NameBuffer;
+ llvm::raw_svector_ostream NameOS(NameBuffer);
+ printName(NameOS);
+ if (NameBuffer.empty())
+ OS << "(anonymous)";
+ else
+ OS << NameBuffer;
+ }
}
void NamedDecl::printNestedNameSpecifier(raw_ostream &OS) const {
@@ -1587,13 +1571,16 @@ void NamedDecl::printNestedNameSpecifier(raw_ostream &OS,
// For ObjC methods and properties, look through categories and use the
// interface as context.
- if (auto *MD = dyn_cast<ObjCMethodDecl>(this))
+ if (auto *MD = dyn_cast<ObjCMethodDecl>(this)) {
if (auto *ID = MD->getClassInterface())
Ctx = ID;
- if (auto *PD = dyn_cast<ObjCPropertyDecl>(this)) {
+ } else if (auto *PD = dyn_cast<ObjCPropertyDecl>(this)) {
if (auto *MD = PD->getGetterMethodDecl())
if (auto *ID = MD->getClassInterface())
Ctx = ID;
+ } else if (auto *ID = dyn_cast<ObjCIvarDecl>(this)) {
+ if (auto *CI = ID->getContainingInterface())
+ Ctx = CI;
}
if (Ctx->isFunctionOrMethod())
@@ -2981,7 +2968,8 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const {
return (proto->getParamType(1).getCanonicalType() == Context.VoidPtrTy);
}
-bool FunctionDecl::isReplaceableGlobalAllocationFunction(bool *IsAligned) const {
+bool FunctionDecl::isReplaceableGlobalAllocationFunction(
+ Optional<unsigned> *AlignmentParam, bool *IsNothrow) const {
if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName)
return false;
if (getDeclName().getCXXOverloadedOperator() != OO_New &&
@@ -3028,9 +3016,9 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction(bool *IsAligned) const
// In C++17, the next parameter can be a 'std::align_val_t' for aligned
// new/delete.
if (Ctx.getLangOpts().AlignedAllocation && !Ty.isNull() && Ty->isAlignValT()) {
- if (IsAligned)
- *IsAligned = true;
Consume();
+ if (AlignmentParam)
+ *AlignmentParam = Params;
}
// Finally, if this is not a sized delete, the final parameter can
@@ -3039,8 +3027,11 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction(bool *IsAligned) const
Ty = Ty->getPointeeType();
if (Ty.getCVRQualifiers() != Qualifiers::Const)
return false;
- if (Ty->isNothrowT())
+ if (Ty->isNothrowT()) {
+ if (IsNothrow)
+ *IsNothrow = true;
Consume();
+ }
}
return Params == FPT->getNumParams();
@@ -3173,8 +3164,8 @@ FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); }
unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const {
unsigned BuiltinID;
- if (const auto *AMAA = getAttr<ArmMveAliasAttr>()) {
- BuiltinID = AMAA->getBuiltinName()->getBuiltinID();
+ if (const auto *ABAA = getAttr<ArmBuiltinAliasAttr>()) {
+ BuiltinID = ABAA->getBuiltinName()->getBuiltinID();
} else {
if (!getIdentifier())
return 0;
@@ -3206,7 +3197,7 @@ unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const {
// If the function is marked "overloadable", it has a different mangled name
// and is not the C library function.
if (!ConsiderWrapperFunctions && hasAttr<OverloadableAttr>() &&
- !hasAttr<ArmMveAliasAttr>())
+ !hasAttr<ArmBuiltinAliasAttr>())
return 0;
if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
@@ -3233,6 +3224,15 @@ unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const {
!(BuiltinID == Builtin::BIprintf || BuiltinID == Builtin::BImalloc))
return 0;
+ // As AMDGCN implementation of OpenMP does not have a device-side standard
+ // library, none of the predefined library functions except printf and malloc
+ // should be treated as a builtin i.e. 0 should be returned for them.
+ if (Context.getTargetInfo().getTriple().isAMDGCN() &&
+ Context.getLangOpts().OpenMPIsDevice &&
+ Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID) &&
+ !(BuiltinID == Builtin::BIprintf || BuiltinID == Builtin::BImalloc))
+ return 0;
+
return BuiltinID;
}
@@ -3264,13 +3264,27 @@ unsigned FunctionDecl::getMinRequiredArguments() const {
if (!getASTContext().getLangOpts().CPlusPlus)
return getNumParams();
+ // Note that it is possible for a parameter with no default argument to
+ // follow a parameter with a default argument.
unsigned NumRequiredArgs = 0;
- for (auto *Param : parameters())
- if (!Param->isParameterPack() && !Param->hasDefaultArg())
- ++NumRequiredArgs;
+ unsigned MinParamsSoFar = 0;
+ for (auto *Param : parameters()) {
+ if (!Param->isParameterPack()) {
+ ++MinParamsSoFar;
+ if (!Param->hasDefaultArg())
+ NumRequiredArgs = MinParamsSoFar;
+ }
+ }
return NumRequiredArgs;
}
+bool FunctionDecl::hasOneParamOrDefaultArgs() const {
+ return getNumParams() == 1 ||
+ (getNumParams() > 1 &&
+ std::all_of(param_begin() + 1, param_end(),
+ [](ParmVarDecl *P) { return P->hasDefaultArg(); }));
+}
+
/// The combination of the extern and inline keywords under MSVC forces
/// the function to be required.
///
@@ -3609,7 +3623,8 @@ bool FunctionDecl::isTemplateInstantiation() const {
return clang::isTemplateInstantiation(getTemplateSpecializationKind());
}
-FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
+FunctionDecl *
+FunctionDecl::getTemplateInstantiationPattern(bool ForDefinition) const {
// If this is a generic lambda call operator specialization, its
// instantiation pattern is always its primary template's pattern
// even if its primary template was instantiated from another
@@ -3626,18 +3641,20 @@ FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
}
if (MemberSpecializationInfo *Info = getMemberSpecializationInfo()) {
- if (!clang::isTemplateInstantiation(Info->getTemplateSpecializationKind()))
+ if (ForDefinition &&
+ !clang::isTemplateInstantiation(Info->getTemplateSpecializationKind()))
return nullptr;
return getDefinitionOrSelf(cast<FunctionDecl>(Info->getInstantiatedFrom()));
}
- if (!clang::isTemplateInstantiation(getTemplateSpecializationKind()))
+ if (ForDefinition &&
+ !clang::isTemplateInstantiation(getTemplateSpecializationKind()))
return nullptr;
if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {
// If we hit a point where the user provided a specialization of this
// template, we're done looking.
- while (!Primary->isMemberSpecialization()) {
+ while (!ForDefinition || !Primary->isMemberSpecialization()) {
auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate();
if (!NewPrimary)
break;
@@ -4422,6 +4439,21 @@ void RecordDecl::setCapturedRecord() {
addAttr(CapturedRecordAttr::CreateImplicit(getASTContext()));
}
+bool RecordDecl::isOrContainsUnion() const {
+ if (isUnion())
+ return true;
+
+ if (const RecordDecl *Def = getDefinition()) {
+ for (const FieldDecl *FD : Def->fields()) {
+ const RecordType *RT = FD->getType()->getAs<RecordType>();
+ if (RT && RT->getDecl()->isOrContainsUnion())
+ return true;
+ }
+ }
+
+ return false;
+}
+
RecordDecl::field_iterator RecordDecl::field_begin() const {
if (hasExternalLexicalStorage() && !hasLoadedFieldsFromExternalStorage())
LoadFieldsFromExternalStorage();
@@ -4493,11 +4525,11 @@ bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const {
ReasonToReject = 5; // is standard layout.
else if (Blacklist.isBlacklistedLocation(EnabledAsanMask, getLocation(),
"field-padding"))
- ReasonToReject = 6; // is in a blacklisted file.
+ ReasonToReject = 6; // is in an excluded file.
else if (Blacklist.isBlacklistedType(EnabledAsanMask,
getQualifiedNameAsString(),
"field-padding"))
- ReasonToReject = 7; // is blacklisted.
+ ReasonToReject = 7; // The type is excluded.
if (EmitRemark) {
if (ReasonToReject >= 0)
@@ -4921,7 +4953,8 @@ static unsigned getNumModuleIdentifiers(Module *Mod) {
ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
Module *Imported,
ArrayRef<SourceLocation> IdentifierLocs)
- : Decl(Import, DC, StartLoc), ImportedAndComplete(Imported, true) {
+ : Decl(Import, DC, StartLoc), ImportedModule(Imported),
+ NextLocalImportAndComplete(nullptr, true) {
assert(getNumModuleIdentifiers(Imported) == IdentifierLocs.size());
auto *StoredLocs = getTrailingObjects<SourceLocation>();
std::uninitialized_copy(IdentifierLocs.begin(), IdentifierLocs.end(),
@@ -4930,7 +4963,8 @@ ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
Module *Imported, SourceLocation EndLoc)
- : Decl(Import, DC, StartLoc), ImportedAndComplete(Imported, false) {
+ : Decl(Import, DC, StartLoc), ImportedModule(Imported),
+ NextLocalImportAndComplete(nullptr, false) {
*getTrailingObjects<SourceLocation>() = EndLoc;
}
@@ -4959,7 +4993,7 @@ ImportDecl *ImportDecl::CreateDeserialized(ASTContext &C, unsigned ID,
}
ArrayRef<SourceLocation> ImportDecl::getIdentifierLocs() const {
- if (!ImportedAndComplete.getInt())
+ if (!isImportComplete())
return None;
const auto *StoredLocs = getTrailingObjects<SourceLocation>();
@@ -4968,7 +5002,7 @@ ArrayRef<SourceLocation> ImportDecl::getIdentifierLocs() const {
}
SourceRange ImportDecl::getSourceRange() const {
- if (!ImportedAndComplete.getInt())
+ if (!isImportComplete())
return SourceRange(getLocation(), *getTrailingObjects<SourceLocation>());
return SourceRange(getLocation(), getIdentifierLocs().back());
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 6ee767ccecf7d..da1eadd9d931d 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -240,15 +240,47 @@ TemplateDecl *Decl::getDescribedTemplate() const {
return nullptr;
}
+const TemplateParameterList *Decl::getDescribedTemplateParams() const {
+ if (auto *TD = getDescribedTemplate())
+ return TD->getTemplateParameters();
+ if (auto *CTPSD = dyn_cast<ClassTemplatePartialSpecializationDecl>(this))
+ return CTPSD->getTemplateParameters();
+ if (auto *VTPSD = dyn_cast<VarTemplatePartialSpecializationDecl>(this))
+ return VTPSD->getTemplateParameters();
+ return nullptr;
+}
+
bool Decl::isTemplated() const {
- // A declaration is dependent if it is a template or a template pattern, or
+ // A declaration is templated if it is a template or a template pattern, or
// is within (lexcially for a friend, semantically otherwise) a dependent
// context.
// FIXME: Should local extern declarations be treated like friends?
if (auto *AsDC = dyn_cast<DeclContext>(this))
return AsDC->isDependentContext();
auto *DC = getFriendObjectKind() ? getLexicalDeclContext() : getDeclContext();
- return DC->isDependentContext() || isTemplateDecl() || getDescribedTemplate();
+ return DC->isDependentContext() || isTemplateDecl() ||
+ getDescribedTemplateParams();
+}
+
+unsigned Decl::getTemplateDepth() const {
+ if (auto *DC = dyn_cast<DeclContext>(this))
+ if (DC->isFileContext())
+ return 0;
+
+ if (auto *TPL = getDescribedTemplateParams())
+ return TPL->getDepth() + 1;
+
+ // If this is a dependent lambda, there might be an enclosing variable
+ // template. In this case, the next step is not the parent DeclContext (or
+ // even a DeclContext at all).
+ auto *RD = dyn_cast<CXXRecordDecl>(this);
+ if (RD && RD->isDependentLambda())
+ if (Decl *Context = RD->getLambdaContextDecl())
+ return Context->getTemplateDepth();
+
+ const DeclContext *DC =
+ getFriendObjectKind() ? getLexicalDeclContext() : getDeclContext();
+ return cast<Decl>(DC)->getTemplateDepth();
}
const DeclContext *Decl::getParentFunctionOrMethod() const {
@@ -332,13 +364,18 @@ void Decl::setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC,
}
}
-bool Decl::isLexicallyWithinFunctionOrMethod() const {
+bool Decl::isInLocalScopeForInstantiation() const {
const DeclContext *LDC = getLexicalDeclContext();
+ if (!LDC->isDependentContext())
+ return false;
while (true) {
if (LDC->isFunctionOrMethod())
return true;
if (!isa<TagDecl>(LDC))
return false;
+ if (const auto *CRD = dyn_cast<CXXRecordDecl>(LDC))
+ if (CRD->isLambda())
+ return true;
LDC = LDC->getLexicalParent();
}
return false;
@@ -378,6 +415,12 @@ ASTContext &Decl::getASTContext() const {
return getTranslationUnitDecl()->getASTContext();
}
+/// Helper to get the language options from the ASTContext.
+/// Defined out of line to avoid depending on ASTContext.h.
+const LangOptions &Decl::getLangOpts() const {
+ return getASTContext().getLangOpts();
+}
+
ASTMutationListener *Decl::getASTMutationListener() const {
return getASTContext().getASTMutationListener();
}
@@ -390,8 +433,10 @@ unsigned Decl::getMaxAlignment() const {
const AttrVec &V = getAttrs();
ASTContext &Ctx = getASTContext();
specific_attr_iterator<AlignedAttr> I(V.begin()), E(V.end());
- for (; I != E; ++I)
- Align = std::max(Align, I->getAlignment(Ctx));
+ for (; I != E; ++I) {
+ if (!I->isAlignmentErrorDependent())
+ Align = std::max(Align, I->getAlignment(Ctx));
+ }
return Align;
}
@@ -454,7 +499,8 @@ ExternalSourceSymbolAttr *Decl::getExternalSourceSymbolAttr() const {
}
bool Decl::hasDefiningAttr() const {
- return hasAttr<AliasAttr>() || hasAttr<IFuncAttr>();
+ return hasAttr<AliasAttr>() || hasAttr<IFuncAttr>() ||
+ hasAttr<LoaderUninitializedAttr>();
}
const Attr *Decl::getDefiningAttr() const {
@@ -462,6 +508,8 @@ const Attr *Decl::getDefiningAttr() const {
return AA;
if (auto *IFA = getAttr<IFuncAttr>())
return IFA;
+ if (auto *NZA = getAttr<LoaderUninitializedAttr>())
+ return NZA;
return nullptr;
}
@@ -587,7 +635,7 @@ AvailabilityResult Decl::getAvailability(std::string *Message,
continue;
if (Message)
- ResultMessage = Deprecated->getMessage();
+ ResultMessage = std::string(Deprecated->getMessage());
Result = AR_Deprecated;
continue;
@@ -595,7 +643,7 @@ AvailabilityResult Decl::getAvailability(std::string *Message,
if (const auto *Unavailable = dyn_cast<UnavailableAttr>(A)) {
if (Message)
- *Message = Unavailable->getMessage();
+ *Message = std::string(Unavailable->getMessage());
return AR_Unavailable;
}
@@ -786,6 +834,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case TranslationUnit:
case ExternCContext:
case Decomposition:
+ case MSGuid:
case UsingDirective:
case BuiltinTemplate:
@@ -804,6 +853,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case OMPCapturedExpr:
case Empty:
case LifetimeExtendedTemporary:
+ case RequiresExprBody:
// Never looked up by name.
return 0;
}
@@ -1177,6 +1227,7 @@ DeclContext *DeclContext::getPrimaryContext() {
case Decl::Captured:
case Decl::OMPDeclareReduction:
case Decl::OMPDeclareMapper:
+ case Decl::RequiresExprBody:
// There is only one DeclContext for these entities.
return this;
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 2ead1e70ea0d6..6f1fd2f14edeb 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -42,6 +42,7 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
@@ -83,10 +84,12 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
HasInheritedConstructor(false), HasInheritedAssignment(false),
NeedOverloadResolutionForCopyConstructor(false),
NeedOverloadResolutionForMoveConstructor(false),
+ NeedOverloadResolutionForCopyAssignment(false),
NeedOverloadResolutionForMoveAssignment(false),
NeedOverloadResolutionForDestructor(false),
DefaultedCopyConstructorIsDeleted(false),
DefaultedMoveConstructorIsDeleted(false),
+ DefaultedCopyAssignmentIsDeleted(false),
DefaultedMoveAssignmentIsDeleted(false),
DefaultedDestructorIsDeleted(false), HasTrivialSpecialMembers(SMF_All),
HasTrivialSpecialMembersForCall(SMF_All),
@@ -434,10 +437,8 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);
// Keep track of the presence of mutable fields.
- if (BaseClassDecl->hasMutableFields()) {
+ if (BaseClassDecl->hasMutableFields())
data().HasMutableFields = true;
- data().NeedOverloadResolutionForCopyConstructor = true;
- }
if (BaseClassDecl->hasUninitializedReferenceMember())
data().HasUninitializedReferenceMember = true;
@@ -510,6 +511,8 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) {
// -- a direct or virtual base class B that cannot be copied/moved [...]
// -- a non-static data member of class type M (or array thereof)
// that cannot be copied or moved [...]
+ if (!Subobj->hasSimpleCopyAssignment())
+ data().NeedOverloadResolutionForCopyAssignment = true;
if (!Subobj->hasSimpleMoveAssignment())
data().NeedOverloadResolutionForMoveAssignment = true;
@@ -663,10 +666,9 @@ bool CXXRecordDecl::lambdaIsDefaultConstructibleAndAssignable() const {
// C++17 [expr.prim.lambda]p21:
// The closure type associated with a lambda-expression has no default
// constructor and a deleted copy assignment operator.
- if (getLambdaCaptureDefault() != LCD_None ||
- getLambdaData().NumCaptures != 0)
+ if (getLambdaCaptureDefault() != LCD_None || capture_size() != 0)
return false;
- return getASTContext().getLangOpts().CPlusPlus2a;
+ return getASTContext().getLangOpts().CPlusPlus20;
}
void CXXRecordDecl::addedMember(Decl *D) {
@@ -782,7 +784,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
// C++20 [dcl.init.aggr]p1:
// An aggregate is an array or a class with no user-declared [...]
// constructors
- if (getASTContext().getLangOpts().CPlusPlus2a
+ if (getASTContext().getLangOpts().CPlusPlus20
? !Constructor->isImplicit()
: (Constructor->isUserProvided() || Constructor->isExplicit()))
data().Aggregate = false;
@@ -978,10 +980,8 @@ void CXXRecordDecl::addedMember(Decl *D) {
}
// Keep track of the presence of mutable fields.
- if (Field->isMutable()) {
+ if (Field->isMutable())
data().HasMutableFields = true;
- data().NeedOverloadResolutionForCopyConstructor = true;
- }
// C++11 [class.union]p8, DR1460:
// If X is a union, a non-static data member of X that is not an anonymous
@@ -1025,10 +1025,12 @@ void CXXRecordDecl::addedMember(Decl *D) {
if (isUnion()) {
data().DefaultedCopyConstructorIsDeleted = true;
data().DefaultedMoveConstructorIsDeleted = true;
+ data().DefaultedCopyAssignmentIsDeleted = true;
data().DefaultedMoveAssignmentIsDeleted = true;
data().DefaultedDestructorIsDeleted = true;
data().NeedOverloadResolutionForCopyConstructor = true;
data().NeedOverloadResolutionForMoveConstructor = true;
+ data().NeedOverloadResolutionForCopyAssignment = true;
data().NeedOverloadResolutionForMoveAssignment = true;
data().NeedOverloadResolutionForDestructor = true;
}
@@ -1095,8 +1097,10 @@ void CXXRecordDecl::addedMember(Decl *D) {
// A defaulted copy/move assignment operator for a class X is defined
// as deleted if X has:
// -- a non-static data member of reference type
- if (T->isReferenceType())
+ if (T->isReferenceType()) {
+ data().DefaultedCopyAssignmentIsDeleted = true;
data().DefaultedMoveAssignmentIsDeleted = true;
+ }
// Bitfields of length 0 are also zero-sized, but we already bailed out for
// those because they are always unnamed.
@@ -1115,6 +1119,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
// parameter.
data().NeedOverloadResolutionForCopyConstructor = true;
data().NeedOverloadResolutionForMoveConstructor = true;
+ data().NeedOverloadResolutionForCopyAssignment = true;
data().NeedOverloadResolutionForMoveAssignment = true;
}
@@ -1128,6 +1133,8 @@ void CXXRecordDecl::addedMember(Decl *D) {
data().DefaultedCopyConstructorIsDeleted = true;
if (FieldRec->hasNonTrivialMoveConstructor())
data().DefaultedMoveConstructorIsDeleted = true;
+ if (FieldRec->hasNonTrivialCopyAssignment())
+ data().DefaultedCopyAssignmentIsDeleted = true;
if (FieldRec->hasNonTrivialMoveAssignment())
data().DefaultedMoveAssignmentIsDeleted = true;
if (FieldRec->hasNonTrivialDestructor())
@@ -1141,6 +1148,8 @@ void CXXRecordDecl::addedMember(Decl *D) {
FieldRec->data().NeedOverloadResolutionForCopyConstructor;
data().NeedOverloadResolutionForMoveConstructor |=
FieldRec->data().NeedOverloadResolutionForMoveConstructor;
+ data().NeedOverloadResolutionForCopyAssignment |=
+ FieldRec->data().NeedOverloadResolutionForCopyAssignment;
data().NeedOverloadResolutionForMoveAssignment |=
FieldRec->data().NeedOverloadResolutionForMoveAssignment;
data().NeedOverloadResolutionForDestructor |=
@@ -1238,9 +1247,15 @@ void CXXRecordDecl::addedMember(Decl *D) {
}
// Keep track of the presence of mutable fields.
- if (FieldRec->hasMutableFields()) {
+ if (FieldRec->hasMutableFields())
data().HasMutableFields = true;
+
+ if (Field->isMutable()) {
+ // Our copy constructor/assignment might call something other than
+ // the subobject's copy constructor/assignment if it's mutable and of
+ // class type.
data().NeedOverloadResolutionForCopyConstructor = true;
+ data().NeedOverloadResolutionForCopyAssignment = true;
}
// C++11 [class.copy]p13:
@@ -1288,7 +1303,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
// Base element type of field is a non-class type.
if (!T->isLiteralType(Context) ||
(!Field->hasInClassInitializer() && !isUnion() &&
- !Context.getLangOpts().CPlusPlus2a))
+ !Context.getLangOpts().CPlusPlus20))
data().DefaultedDefaultConstructorIsConstexpr = false;
// C++11 [class.copy]p23:
@@ -1296,8 +1311,10 @@ void CXXRecordDecl::addedMember(Decl *D) {
// as deleted if X has:
// -- a non-static data member of const non-class type (or array
// thereof)
- if (T.isConstQualified())
+ if (T.isConstQualified()) {
+ data().DefaultedCopyAssignmentIsDeleted = true;
data().DefaultedMoveAssignmentIsDeleted = true;
+ }
}
// C++14 [meta.unary.prop]p4:
@@ -1366,6 +1383,27 @@ void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) {
data().DeclaredNonTrivialSpecialMembers |= SMKind;
}
+void CXXRecordDecl::setCaptures(ArrayRef<LambdaCapture> Captures) {
+ ASTContext &Context = getASTContext();
+ CXXRecordDecl::LambdaDefinitionData &Data = getLambdaData();
+
+ // Copy captures.
+ Data.NumCaptures = Captures.size();
+ Data.NumExplicitCaptures = 0;
+ Data.Captures = (LambdaCapture *)Context.Allocate(sizeof(LambdaCapture) *
+ Captures.size());
+ LambdaCapture *ToCapture = Data.Captures;
+ for (unsigned I = 0, N = Captures.size(); I != N; ++I) {
+ if (Captures[I].isExplicit())
+ ++Data.NumExplicitCaptures;
+
+ *ToCapture++ = Captures[I];
+ }
+
+ if (!lambdaIsDefaultConstructibleAndAssignable())
+ Data.DefaultedCopyAssignmentIsDeleted = true;
+}
+
void CXXRecordDecl::setTrivialForCallFlags(CXXMethodDecl *D) {
unsigned SMKind = 0;
@@ -1923,6 +1961,18 @@ bool CXXRecordDecl::mayBeAbstract() const {
return false;
}
+bool CXXRecordDecl::isEffectivelyFinal() const {
+ auto *Def = getDefinition();
+ if (!Def)
+ return false;
+ if (Def->hasAttr<FinalAttr>())
+ return true;
+ if (const auto *Dtor = Def->getDestructor())
+ if (Dtor->hasAttr<FinalAttr>())
+ return true;
+ return false;
+}
+
void CXXDeductionGuideDecl::anchor() {}
bool ExplicitSpecifier::isEquivalent(const ExplicitSpecifier Other) const {
@@ -1968,6 +2018,16 @@ CXXDeductionGuideDecl *CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C,
QualType(), nullptr, SourceLocation());
}
+RequiresExprBodyDecl *RequiresExprBodyDecl::Create(
+ ASTContext &C, DeclContext *DC, SourceLocation StartLoc) {
+ return new (C, DC) RequiresExprBodyDecl(C, DC, StartLoc);
+}
+
+RequiresExprBodyDecl *RequiresExprBodyDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID) {
+ return new (C, ID) RequiresExprBodyDecl(C, nullptr, SourceLocation());
+}
+
void CXXMethodDecl::anchor() {}
bool CXXMethodDecl::isStatic() const {
@@ -2028,17 +2088,36 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD,
if (auto *MD = getCorrespondingMethodDeclaredInClass(RD, MayBeBase))
return MD;
+ llvm::SmallVector<CXXMethodDecl*, 4> FinalOverriders;
+ auto AddFinalOverrider = [&](CXXMethodDecl *D) {
+ // If this function is overridden by a candidate final overrider, it is not
+ // a final overrider.
+ for (CXXMethodDecl *OtherD : FinalOverriders) {
+ if (declaresSameEntity(D, OtherD) || recursivelyOverrides(OtherD, D))
+ return;
+ }
+
+ // Other candidate final overriders might be overridden by this function.
+ FinalOverriders.erase(
+ std::remove_if(FinalOverriders.begin(), FinalOverriders.end(),
+ [&](CXXMethodDecl *OtherD) {
+ return recursivelyOverrides(D, OtherD);
+ }),
+ FinalOverriders.end());
+
+ FinalOverriders.push_back(D);
+ };
+
for (const auto &I : RD->bases()) {
const RecordType *RT = I.getType()->getAs<RecordType>();
if (!RT)
continue;
const auto *Base = cast<CXXRecordDecl>(RT->getDecl());
- CXXMethodDecl *T = this->getCorrespondingMethodInClass(Base);
- if (T)
- return T;
+ if (CXXMethodDecl *D = this->getCorrespondingMethodInClass(Base))
+ AddFinalOverrider(D);
}
- return nullptr;
+ return FinalOverriders.size() == 1 ? FinalOverriders.front() : nullptr;
}
CXXMethodDecl *CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
@@ -2095,6 +2174,11 @@ CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base,
CXXMethodDecl *DevirtualizedMethod =
getCorrespondingMethodInClass(BestDynamicDecl);
+ // If there final overrider in the dynamic type is ambiguous, we can't
+ // devirtualize this call.
+ if (!DevirtualizedMethod)
+ return nullptr;
+
// If that method is pure virtual, we can't devirtualize. If this code is
// reached, the result would be UB, not a direct call to the derived class
// function, and we can't assume the derived class function is defined.
@@ -2106,14 +2190,10 @@ CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base,
return DevirtualizedMethod;
// Similarly, if the class itself or its destructor is marked 'final',
- // the class can't be derived from and we can therefore devirtualize the
+ // the class can't be derived from and we can therefore devirtualize the
// member function call.
- if (BestDynamicDecl->hasAttr<FinalAttr>())
+ if (BestDynamicDecl->isEffectivelyFinal())
return DevirtualizedMethod;
- if (const auto *dtor = BestDynamicDecl->getDestructor()) {
- if (dtor->hasAttr<FinalAttr>())
- return DevirtualizedMethod;
- }
if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
@@ -2322,17 +2402,15 @@ QualType CXXMethodDecl::getThisType() const {
// volatile X*, and if the member function is declared const volatile,
// the type of this is const volatile X*.
assert(isInstance() && "No 'this' for static methods!");
-
- return CXXMethodDecl::getThisType(getType()->getAs<FunctionProtoType>(),
+ return CXXMethodDecl::getThisType(getType()->castAs<FunctionProtoType>(),
getParent());
}
QualType CXXMethodDecl::getThisObjectType() const {
// Ditto getThisType.
assert(isInstance() && "No 'this' for static methods!");
-
- return CXXMethodDecl::getThisObjectType(getType()->getAs<FunctionProtoType>(),
- getParent());
+ return CXXMethodDecl::getThisObjectType(
+ getType()->castAs<FunctionProtoType>(), getParent());
}
bool CXXMethodDecl::hasInlineBody() const {
@@ -2508,11 +2586,11 @@ CXXConstructorDecl *CXXConstructorDecl::getTargetConstructor() const {
}
bool CXXConstructorDecl::isDefaultConstructor() const {
- // C++ [class.ctor]p5:
- // A default constructor for a class X is a constructor of class
- // X that can be called without an argument.
- return (getNumParams() == 0) ||
- (getNumParams() > 0 && getParamDecl(0)->hasDefaultArg());
+ // C++ [class.default.ctor]p1:
+ // A default constructor for a class X is a constructor of class X for
+ // which each parameter that is not a function parameter pack has a default
+ // argument (including the case of a constructor with no parameters)
+ return getMinRequiredArguments() == 0;
}
bool
@@ -2523,7 +2601,7 @@ CXXConstructorDecl::isCopyConstructor(unsigned &TypeQuals) const {
bool CXXConstructorDecl::isMoveConstructor(unsigned &TypeQuals) const {
return isCopyOrMoveConstructor(TypeQuals) &&
- getParamDecl(0)->getType()->isRValueReferenceType();
+ getParamDecl(0)->getType()->isRValueReferenceType();
}
/// Determine whether this is a copy or move constructor.
@@ -2538,10 +2616,8 @@ bool CXXConstructorDecl::isCopyOrMoveConstructor(unsigned &TypeQuals) const {
// first parameter is of type X&&, const X&&, volatile X&&, or
// const volatile X&&, and either there are no other parameters or else
// all other parameters have default arguments.
- if ((getNumParams() < 1) ||
- (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) ||
- (getPrimaryTemplate() != nullptr) ||
- (getDescribedFunctionTemplate() != nullptr))
+ if (!hasOneParamOrDefaultArgs() || getPrimaryTemplate() != nullptr ||
+ getDescribedFunctionTemplate() != nullptr)
return false;
const ParmVarDecl *Param = getParamDecl(0);
@@ -2578,18 +2654,16 @@ bool CXXConstructorDecl::isConvertingConstructor(bool AllowExplicit) const {
if (isExplicit() && !AllowExplicit)
return false;
- return (getNumParams() == 0 &&
- getType()->castAs<FunctionProtoType>()->isVariadic()) ||
- (getNumParams() == 1) ||
- (getNumParams() > 1 &&
- (getParamDecl(1)->hasDefaultArg() ||
- getParamDecl(1)->isParameterPack()));
+ // FIXME: This has nothing to do with the definition of converting
+ // constructor, but is convenient for how we use this function in overload
+ // resolution.
+ return getNumParams() == 0
+ ? getType()->castAs<FunctionProtoType>()->isVariadic()
+ : getMinRequiredArguments() <= 1;
}
bool CXXConstructorDecl::isSpecializationCopyingObject() const {
- if ((getNumParams() < 1) ||
- (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) ||
- (getDescribedFunctionTemplate() != nullptr))
+ if (!hasOneParamOrDefaultArgs() || getDescribedFunctionTemplate() != nullptr)
return false;
const ParmVarDecl *Param = getParamDecl(0);
@@ -3054,7 +3128,7 @@ VarDecl *BindingDecl::getHoldingVar() const {
if (!DRE)
return nullptr;
- auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
+ auto *VD = cast<VarDecl>(DRE->getDecl());
assert(VD->isImplicit() && "holding var for binding decl not implicit");
return VD;
}
@@ -3117,6 +3191,102 @@ MSPropertyDecl *MSPropertyDecl::CreateDeserialized(ASTContext &C,
SourceLocation(), nullptr, nullptr);
}
+void MSGuidDecl::anchor() {}
+
+MSGuidDecl::MSGuidDecl(DeclContext *DC, QualType T, Parts P)
+ : ValueDecl(Decl::MSGuid, DC, SourceLocation(), DeclarationName(), T),
+ PartVal(P), APVal() {}
+
+MSGuidDecl *MSGuidDecl::Create(const ASTContext &C, QualType T, Parts P) {
+ DeclContext *DC = C.getTranslationUnitDecl();
+ return new (C, DC) MSGuidDecl(DC, T, P);
+}
+
+MSGuidDecl *MSGuidDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ return new (C, ID) MSGuidDecl(nullptr, QualType(), Parts());
+}
+
+void MSGuidDecl::printName(llvm::raw_ostream &OS) const {
+ OS << llvm::format("GUID{%08" PRIx32 "-%04" PRIx16 "-%04" PRIx16 "-",
+ PartVal.Part1, PartVal.Part2, PartVal.Part3);
+ unsigned I = 0;
+ for (uint8_t Byte : PartVal.Part4And5) {
+ OS << llvm::format("%02" PRIx8, Byte);
+ if (++I == 2)
+ OS << '-';
+ }
+ OS << '}';
+}
+
+/// Determine if T is a valid 'struct _GUID' of the shape that we expect.
+static bool isValidStructGUID(ASTContext &Ctx, QualType T) {
+ // FIXME: We only need to check this once, not once each time we compute a
+ // GUID APValue.
+ using MatcherRef = llvm::function_ref<bool(QualType)>;
+
+ auto IsInt = [&Ctx](unsigned N) {
+ return [&Ctx, N](QualType T) {
+ return T->isUnsignedIntegerOrEnumerationType() &&
+ Ctx.getIntWidth(T) == N;
+ };
+ };
+
+ auto IsArray = [&Ctx](MatcherRef Elem, unsigned N) {
+ return [&Ctx, Elem, N](QualType T) {
+ const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(T);
+ return CAT && CAT->getSize() == N && Elem(CAT->getElementType());
+ };
+ };
+
+ auto IsStruct = [](std::initializer_list<MatcherRef> Fields) {
+ return [Fields](QualType T) {
+ const RecordDecl *RD = T->getAsRecordDecl();
+ if (!RD || RD->isUnion())
+ return false;
+ RD = RD->getDefinition();
+ if (!RD)
+ return false;
+ if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
+ if (CXXRD->getNumBases())
+ return false;
+ auto MatcherIt = Fields.begin();
+ for (const FieldDecl *FD : RD->fields()) {
+ if (FD->isUnnamedBitfield()) continue;
+ if (FD->isBitField() || MatcherIt == Fields.end() ||
+ !(*MatcherIt)(FD->getType()))
+ return false;
+ ++MatcherIt;
+ }
+ return MatcherIt == Fields.end();
+ };
+ };
+
+ // We expect an {i32, i16, i16, [8 x i8]}.
+ return IsStruct({IsInt(32), IsInt(16), IsInt(16), IsArray(IsInt(8), 8)})(T);
+}
+
+APValue &MSGuidDecl::getAsAPValue() const {
+ if (APVal.isAbsent() && isValidStructGUID(getASTContext(), getType())) {
+ using llvm::APInt;
+ using llvm::APSInt;
+ APVal = APValue(APValue::UninitStruct(), 0, 4);
+ APVal.getStructField(0) = APValue(APSInt(APInt(32, PartVal.Part1), true));
+ APVal.getStructField(1) = APValue(APSInt(APInt(16, PartVal.Part2), true));
+ APVal.getStructField(2) = APValue(APSInt(APInt(16, PartVal.Part3), true));
+ APValue &Arr = APVal.getStructField(3) =
+ APValue(APValue::UninitArray(), 8, 8);
+ for (unsigned I = 0; I != 8; ++I) {
+ Arr.getArrayInitializedElt(I) =
+ APValue(APSInt(APInt(8, PartVal.Part4And5[I]), true));
+ }
+ // Register this APValue to be destroyed if necessary. (Note that the
+ // MSGuidDecl destructor is never run.)
+ getASTContext().addDestruction(&APVal);
+ }
+
+ return APVal;
+}
+
static const char *getAccessName(AccessSpecifier AS) {
switch (AS) {
case AS_none:
diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp
index 9a84e3c4a5107..5c8b34731f363 100644
--- a/clang/lib/AST/DeclObjC.cpp
+++ b/clang/lib/AST/DeclObjC.cpp
@@ -94,7 +94,7 @@ ObjCContainerDecl::getMethod(Selector Sel, bool isInstance,
// methods there.
if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(this)) {
if (const ObjCProtocolDecl *Def = Proto->getDefinition())
- if (Def->isHidden() && !AllowHidden)
+ if (!Def->isUnconditionallyVisible() && !AllowHidden)
return nullptr;
}
@@ -146,7 +146,8 @@ bool ObjCContainerDecl::HasUserDeclaredSetterMethod(
// auto-synthesized).
for (const auto *P : Cat->properties())
if (P->getIdentifier() == Property->getIdentifier()) {
- if (P->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readwrite)
+ if (P->getPropertyAttributes() &
+ ObjCPropertyAttribute::kind_readwrite)
return true;
break;
}
@@ -180,7 +181,7 @@ ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC,
// property.
if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(DC)) {
if (const ObjCProtocolDecl *Def = Proto->getDefinition())
- if (Def->isHidden())
+ if (!Def->isUnconditionallyVisible())
return nullptr;
}
@@ -238,7 +239,7 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration(
// Don't find properties within hidden protocol definitions.
if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(this)) {
if (const ObjCProtocolDecl *Def = Proto->getDefinition())
- if (Def->isHidden())
+ if (!Def->isUnconditionallyVisible())
return nullptr;
}
@@ -1361,25 +1362,23 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
return Found;
} else {
// Determine whether the container is a class.
- ClassDecl = dyn_cast<ObjCInterfaceDecl>(Container);
+ ClassDecl = cast<ObjCInterfaceDecl>(Container);
}
+ assert(ClassDecl && "Failed to find main class");
// If we have a class, check its visible extensions.
- if (ClassDecl) {
- for (const auto *Ext : ClassDecl->visible_extensions()) {
- if (Ext == Container)
- continue;
-
- if (const auto *Found = findMatchingProperty(Ext))
- return Found;
- }
+ for (const auto *Ext : ClassDecl->visible_extensions()) {
+ if (Ext == Container)
+ continue;
+ if (const auto *Found = findMatchingProperty(Ext))
+ return Found;
}
assert(isSynthesizedAccessorStub() && "expected an accessor stub");
+
for (const auto *Cat : ClassDecl->known_categories()) {
if (Cat == Container)
continue;
-
if (const auto *Found = findMatchingProperty(Cat))
return Found;
}
@@ -1920,7 +1919,7 @@ ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel,
// If there is no definition or the definition is hidden, we don't find
// anything.
const ObjCProtocolDecl *Def = getDefinition();
- if (!Def || Def->isHidden())
+ if (!Def || !Def->isUnconditionallyVisible())
return nullptr;
if ((MethodDecl = getMethod(Sel, isInstance)))
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 4cedcbed06447..2e48b2b46c4da 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -105,6 +105,8 @@ namespace {
void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D);
void VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D);
void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D);
+ void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP);
+ void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *NTTP);
void printTemplateParameters(const TemplateParameterList *Params,
bool OmitTemplateKW = false);
@@ -287,12 +289,10 @@ void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) {
}
void DeclPrinter::Print(AccessSpecifier AS) {
- switch(AS) {
- case AS_none: llvm_unreachable("No access specifier!");
- case AS_public: Out << "public"; break;
- case AS_protected: Out << "protected"; break;
- case AS_private: Out << "private"; break;
- }
+ const auto AccessSpelling = getAccessSpelling(AS);
+ if (AccessSpelling.empty())
+ llvm_unreachable("No access specifier!");
+ Out << AccessSpelling;
}
void DeclPrinter::PrintConstructorInitializers(CXXConstructorDecl *CDecl,
@@ -530,7 +530,7 @@ void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
Out << ' ' << *D;
- if (D->isFixed() && D->getASTContext().getLangOpts().CPlusPlus11)
+ if (D->isFixed())
Out << " : " << D->getIntegerType().stream(Policy);
if (D->isCompleteDefinition()) {
@@ -1051,37 +1051,10 @@ void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params,
else
NeedComma = true;
- if (auto TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
-
- if (const TypeConstraint *TC = TTP->getTypeConstraint())
- TC->print(Out, Policy);
- else if (TTP->wasDeclaredWithTypename())
- Out << "typename";
- else
- Out << "class";
-
- if (TTP->isParameterPack())
- Out << " ...";
- else if (!TTP->getName().empty())
- Out << ' ';
-
- Out << *TTP;
-
- if (TTP->hasDefaultArgument()) {
- Out << " = ";
- Out << TTP->getDefaultArgument().getAsString(Policy);
- };
+ if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
+ VisitTemplateTypeParmDecl(TTP);
} else if (auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
- StringRef Name;
- if (IdentifierInfo *II = NTTP->getIdentifier())
- Name = II->getName();
- printDeclType(NTTP->getType(), Name, NTTP->isParameterPack());
-
- if (NTTP->hasDefaultArgument()) {
- Out << " = ";
- NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy,
- Indentation);
- }
+ VisitNonTypeTemplateParmDecl(NTTP);
} else if (auto TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) {
VisitTemplateDecl(TTPD);
// FIXME: print the default argument, if present.
@@ -1401,7 +1374,12 @@ void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
}
void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
- Out << "@implementation " << *PID->getClassInterface() << '(' << *PID <<")\n";
+ Out << "@implementation ";
+ if (const auto *CID = PID->getClassInterface())
+ Out << *CID;
+ else
+ Out << "<<error-type>>";
+ Out << '(' << *PID << ")\n";
VisitDeclContext(PID, false);
Out << "@end";
@@ -1409,7 +1387,11 @@ void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
}
void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) {
- Out << "@interface " << *PID->getClassInterface();
+ Out << "@interface ";
+ if (const auto *CID = PID->getClassInterface())
+ Out << *CID;
+ else
+ Out << "<<error-type>>";
if (auto TypeParams = PID->getTypeParamList()) {
PrintObjCTypeParams(TypeParams);
}
@@ -1453,85 +1435,83 @@ void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
QualType T = PDecl->getType();
Out << "@property";
- if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) {
+ if (PDecl->getPropertyAttributes() != ObjCPropertyAttribute::kind_noattr) {
bool first = true;
Out << "(";
- if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_class) {
+ if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_class) {
Out << (first ? "" : ", ") << "class";
first = false;
}
- if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_direct) {
+ if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_direct) {
Out << (first ? "" : ", ") << "direct";
first = false;
}
if (PDecl->getPropertyAttributes() &
- ObjCPropertyDecl::OBJC_PR_nonatomic) {
+ ObjCPropertyAttribute::kind_nonatomic) {
Out << (first ? "" : ", ") << "nonatomic";
first = false;
}
- if (PDecl->getPropertyAttributes() &
- ObjCPropertyDecl::OBJC_PR_atomic) {
+ if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_atomic) {
Out << (first ? "" : ", ") << "atomic";
first = false;
}
- if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) {
+ if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_assign) {
Out << (first ? "" : ", ") << "assign";
first = false;
}
- if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) {
+ if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_retain) {
Out << (first ? "" : ", ") << "retain";
first = false;
}
- if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_strong) {
+ if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_strong) {
Out << (first ? "" : ", ") << "strong";
first = false;
}
- if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) {
+ if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_copy) {
Out << (first ? "" : ", ") << "copy";
first = false;
}
- if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak) {
+ if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak) {
Out << (first ? "" : ", ") << "weak";
first = false;
}
- if (PDecl->getPropertyAttributes()
- & ObjCPropertyDecl::OBJC_PR_unsafe_unretained) {
+ if (PDecl->getPropertyAttributes() &
+ ObjCPropertyAttribute::kind_unsafe_unretained) {
Out << (first ? "" : ", ") << "unsafe_unretained";
first = false;
}
if (PDecl->getPropertyAttributes() &
- ObjCPropertyDecl::OBJC_PR_readwrite) {
+ ObjCPropertyAttribute::kind_readwrite) {
Out << (first ? "" : ", ") << "readwrite";
first = false;
}
- if (PDecl->getPropertyAttributes() &
- ObjCPropertyDecl::OBJC_PR_readonly) {
+ if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly) {
Out << (first ? "" : ", ") << "readonly";
first = false;
}
- if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) {
+ if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_getter) {
Out << (first ? "" : ", ") << "getter = ";
PDecl->getGetterName().print(Out);
first = false;
}
- if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) {
+ if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_setter) {
Out << (first ? "" : ", ") << "setter = ";
PDecl->getSetterName().print(Out);
first = false;
}
if (PDecl->getPropertyAttributes() &
- ObjCPropertyDecl::OBJC_PR_nullability) {
+ ObjCPropertyAttribute::kind_nullability) {
if (auto nullability = AttributedType::stripOuterNullability(T)) {
if (*nullability == NullabilityKind::Unspecified &&
(PDecl->getPropertyAttributes() &
- ObjCPropertyDecl::OBJC_PR_null_resettable)) {
+ ObjCPropertyAttribute::kind_null_resettable)) {
Out << (first ? "" : ", ") << "null_resettable";
} else {
Out << (first ? "" : ", ")
@@ -1705,3 +1685,36 @@ void DeclPrinter::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) {
D->getInit()->printPretty(Out, nullptr, Policy, Indentation);
}
+void DeclPrinter::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP) {
+ if (const TypeConstraint *TC = TTP->getTypeConstraint())
+ TC->print(Out, Policy);
+ else if (TTP->wasDeclaredWithTypename())
+ Out << "typename";
+ else
+ Out << "class";
+
+ if (TTP->isParameterPack())
+ Out << " ...";
+ else if (!TTP->getName().empty())
+ Out << ' ';
+
+ Out << *TTP;
+
+ if (TTP->hasDefaultArgument()) {
+ Out << " = ";
+ Out << TTP->getDefaultArgument().getAsString(Policy);
+ }
+}
+
+void DeclPrinter::VisitNonTypeTemplateParmDecl(
+ const NonTypeTemplateParmDecl *NTTP) {
+ StringRef Name;
+ if (IdentifierInfo *II = NTTP->getIdentifier())
+ Name = II->getName();
+ printDeclType(NTTP->getType(), Name, NTTP->isParameterPack());
+
+ if (NTTP->hasDefaultArgument()) {
+ Out << " = ";
+ NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy, Indentation);
+ }
+}
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 95a2e26e0df84..7857e75f57a18 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -164,10 +164,15 @@ static void AdoptTemplateParameterList(TemplateParameterList *Params,
void TemplateParameterList::
getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
if (HasConstrainedParameters)
- for (const NamedDecl *Param : *this)
- if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
+ for (const NamedDecl *Param : *this) {
+ if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
if (const auto *TC = TTP->getTypeConstraint())
AC.push_back(TC->getImmediatelyDeclaredConstraint());
+ } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+ if (const Expr *E = NTTP->getPlaceholderTypeConstraint())
+ AC.push_back(E);
+ }
+ }
if (HasRequiresClause)
AC.push_back(getRequiresClause());
}
@@ -483,7 +488,10 @@ static void ProfileTemplateParameterList(ASTContext &C,
if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(D)) {
ID.AddInteger(1);
ID.AddBoolean(TTP->isParameterPack());
- // TODO: Concepts: profile type-constraints.
+ ID.AddBoolean(TTP->hasTypeConstraint());
+ if (const TypeConstraint *TC = TTP->getTypeConstraint())
+ TC->getImmediatelyDeclaredConstraint()->Profile(ID, C,
+ /*Canonical=*/true);
continue;
}
const auto *TTP = cast<TemplateTemplateParmDecl>(D);
@@ -684,8 +692,14 @@ NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
unsigned D, unsigned P, IdentifierInfo *Id,
QualType T, bool ParameterPack,
TypeSourceInfo *TInfo) {
- return new (C, DC) NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id,
- T, ParameterPack, TInfo);
+ AutoType *AT =
+ C.getLangOpts().CPlusPlus20 ? T->getContainedAutoType() : nullptr;
+ return new (C, DC,
+ additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>,
+ Expr *>(0,
+ AT && AT->isConstrained() ? 1 : 0))
+ NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id, T, ParameterPack,
+ TInfo);
}
NonTypeTemplateParmDecl *NonTypeTemplateParmDecl::Create(
@@ -693,26 +707,34 @@ NonTypeTemplateParmDecl *NonTypeTemplateParmDecl::Create(
SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo, ArrayRef<QualType> ExpandedTypes,
ArrayRef<TypeSourceInfo *> ExpandedTInfos) {
+ AutoType *AT = TInfo->getType()->getContainedAutoType();
return new (C, DC,
- additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>>(
- ExpandedTypes.size()))
+ additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>,
+ Expr *>(
+ ExpandedTypes.size(), AT && AT->isConstrained() ? 1 : 0))
NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id, T, TInfo,
ExpandedTypes, ExpandedTInfos);
}
NonTypeTemplateParmDecl *
-NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) NonTypeTemplateParmDecl(nullptr, SourceLocation(),
- SourceLocation(), 0, 0, nullptr,
- QualType(), false, nullptr);
+NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
+ bool HasTypeConstraint) {
+ return new (C, ID, additionalSizeToAlloc<std::pair<QualType,
+ TypeSourceInfo *>,
+ Expr *>(0,
+ HasTypeConstraint ? 1 : 0))
+ NonTypeTemplateParmDecl(nullptr, SourceLocation(), SourceLocation(),
+ 0, 0, nullptr, QualType(), false, nullptr);
}
NonTypeTemplateParmDecl *
NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
- unsigned NumExpandedTypes) {
+ unsigned NumExpandedTypes,
+ bool HasTypeConstraint) {
auto *NTTP =
- new (C, ID, additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>>(
- NumExpandedTypes))
+ new (C, ID, additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>,
+ Expr *>(
+ NumExpandedTypes, HasTypeConstraint ? 1 : 0))
NonTypeTemplateParmDecl(nullptr, SourceLocation(), SourceLocation(),
0, 0, nullptr, QualType(), nullptr, None,
None);
@@ -1408,4 +1430,4 @@ void TypeConstraint::print(llvm::raw_ostream &OS, PrintingPolicy Policy) const {
ArgLoc.getArgument().print(Policy, OS);
OS << ">";
}
-} \ No newline at end of file
+}
diff --git a/clang/lib/AST/DeclarationName.cpp b/clang/lib/AST/DeclarationName.cpp
index 4eb11bc57e521..ecf676c9936d1 100644
--- a/clang/lib/AST/DeclarationName.cpp
+++ b/clang/lib/AST/DeclarationName.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/OpenMPClause.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
@@ -138,8 +139,19 @@ void DeclarationName::print(raw_ostream &OS,
const PrintingPolicy &Policy) const {
switch (getNameKind()) {
case DeclarationName::Identifier:
- if (const IdentifierInfo *II = getAsIdentifierInfo())
- OS << II->getName();
+ if (const IdentifierInfo *II = getAsIdentifierInfo()) {
+ StringRef Name = II->getName();
+ // If this is a mangled OpenMP variant name we strip off the mangling for
+ // printing. It should not be visible to the user at all.
+ if (II->isMangledOpenMPVariantName()) {
+ std::pair<StringRef, StringRef> NameContextPair =
+ Name.split(getOpenMPVariantManglingSeparatorStr());
+ OS << NameContextPair.first << "["
+ << OMPTraitInfo(NameContextPair.second) << "]";
+ } else {
+ OS << Name;
+ }
+ }
return;
case DeclarationName::ObjCZeroArgSelector:
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 73ddbc62482dd..399e7e13c4459 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -14,9 +14,11 @@
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/ComputeDependence.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DependenceFlags.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/Mangle.h"
@@ -242,6 +244,7 @@ static void AssertResultStorageKind(ConstantExpr::ResultStorageKind Kind) {
assert((Kind == ConstantExpr::RSK_APValue ||
Kind == ConstantExpr::RSK_Int64 || Kind == ConstantExpr::RSK_None) &&
"Invalid StorageKind Value");
+ (void)Kind;
}
ConstantExpr::ResultStorageKind
@@ -266,29 +269,31 @@ ConstantExpr::getStorageKind(const Type *T, const ASTContext &Context) {
return ConstantExpr::RSK_APValue;
}
-void ConstantExpr::DefaultInit(ResultStorageKind StorageKind) {
+ConstantExpr::ConstantExpr(Expr *SubExpr, ResultStorageKind StorageKind,
+ bool IsImmediateInvocation)
+ : FullExpr(ConstantExprClass, SubExpr) {
ConstantExprBits.ResultKind = StorageKind;
ConstantExprBits.APValueKind = APValue::None;
+ ConstantExprBits.IsUnsigned = false;
+ ConstantExprBits.BitWidth = 0;
ConstantExprBits.HasCleanup = false;
+ ConstantExprBits.IsImmediateInvocation = IsImmediateInvocation;
+
if (StorageKind == ConstantExpr::RSK_APValue)
::new (getTrailingObjects<APValue>()) APValue();
}
-ConstantExpr::ConstantExpr(Expr *subexpr, ResultStorageKind StorageKind)
- : FullExpr(ConstantExprClass, subexpr) {
- DefaultInit(StorageKind);
-}
-
ConstantExpr *ConstantExpr::Create(const ASTContext &Context, Expr *E,
- ResultStorageKind StorageKind) {
+ ResultStorageKind StorageKind,
+ bool IsImmediateInvocation) {
assert(!isa<ConstantExpr>(E));
AssertResultStorageKind(StorageKind);
+
unsigned Size = totalSizeToAlloc<APValue, uint64_t>(
StorageKind == ConstantExpr::RSK_APValue,
StorageKind == ConstantExpr::RSK_Int64);
void *Mem = Context.Allocate(Size, alignof(ConstantExpr));
- ConstantExpr *Self = new (Mem) ConstantExpr(E, StorageKind);
- return Self;
+ return new (Mem) ConstantExpr(E, StorageKind, IsImmediateInvocation);
}
ConstantExpr *ConstantExpr::Create(const ASTContext &Context, Expr *E,
@@ -299,25 +304,27 @@ ConstantExpr *ConstantExpr::Create(const ASTContext &Context, Expr *E,
return Self;
}
-ConstantExpr::ConstantExpr(ResultStorageKind StorageKind, EmptyShell Empty)
+ConstantExpr::ConstantExpr(EmptyShell Empty, ResultStorageKind StorageKind)
: FullExpr(ConstantExprClass, Empty) {
- DefaultInit(StorageKind);
+ ConstantExprBits.ResultKind = StorageKind;
+
+ if (StorageKind == ConstantExpr::RSK_APValue)
+ ::new (getTrailingObjects<APValue>()) APValue();
}
ConstantExpr *ConstantExpr::CreateEmpty(const ASTContext &Context,
- ResultStorageKind StorageKind,
- EmptyShell Empty) {
+ ResultStorageKind StorageKind) {
AssertResultStorageKind(StorageKind);
+
unsigned Size = totalSizeToAlloc<APValue, uint64_t>(
StorageKind == ConstantExpr::RSK_APValue,
StorageKind == ConstantExpr::RSK_Int64);
void *Mem = Context.Allocate(Size, alignof(ConstantExpr));
- ConstantExpr *Self = new (Mem) ConstantExpr(StorageKind, Empty);
- return Self;
+ return new (Mem) ConstantExpr(EmptyShell(), StorageKind);
}
void ConstantExpr::MoveIntoResult(APValue &Value, const ASTContext &Context) {
- assert(getStorageKind(Value) == ConstantExprBits.ResultKind &&
+ assert((unsigned)getStorageKind(Value) <= ConstantExprBits.ResultKind &&
"Invalid storage for this value kind");
ConstantExprBits.APValueKind = Value.getKind();
switch (ConstantExprBits.ResultKind) {
@@ -352,6 +359,8 @@ llvm::APSInt ConstantExpr::getResultAsAPSInt() const {
}
APValue ConstantExpr::getAPValueResult() const {
+ assert(hasAPValueResult());
+
switch (ConstantExprBits.ResultKind) {
case ConstantExpr::RSK_APValue:
return APValueResult();
@@ -365,125 +374,12 @@ APValue ConstantExpr::getAPValueResult() const {
llvm_unreachable("invalid ResultKind");
}
-/// Compute the type-, value-, and instantiation-dependence of a
-/// declaration reference
-/// based on the declaration being referenced.
-static void computeDeclRefDependence(const ASTContext &Ctx, NamedDecl *D,
- QualType T, bool &TypeDependent,
- bool &ValueDependent,
- bool &InstantiationDependent) {
- TypeDependent = false;
- ValueDependent = false;
- InstantiationDependent = false;
-
- // (TD) C++ [temp.dep.expr]p3:
- // An id-expression is type-dependent if it contains:
- //
- // and
- //
- // (VD) C++ [temp.dep.constexpr]p2:
- // An identifier is value-dependent if it is:
-
- // (TD) - an identifier that was declared with dependent type
- // (VD) - a name declared with a dependent type,
- if (T->isDependentType()) {
- TypeDependent = true;
- ValueDependent = true;
- InstantiationDependent = true;
- return;
- } else if (T->isInstantiationDependentType()) {
- InstantiationDependent = true;
- }
-
- // (TD) - a conversion-function-id that specifies a dependent type
- if (D->getDeclName().getNameKind()
- == DeclarationName::CXXConversionFunctionName) {
- QualType T = D->getDeclName().getCXXNameType();
- if (T->isDependentType()) {
- TypeDependent = true;
- ValueDependent = true;
- InstantiationDependent = true;
- return;
- }
-
- if (T->isInstantiationDependentType())
- InstantiationDependent = true;
- }
-
- // (VD) - the name of a non-type template parameter,
- if (isa<NonTypeTemplateParmDecl>(D)) {
- ValueDependent = true;
- InstantiationDependent = true;
- return;
- }
-
- // (VD) - a constant with integral or enumeration type and is
- // initialized with an expression that is value-dependent.
- // (VD) - a constant with literal type and is initialized with an
- // expression that is value-dependent [C++11].
- // (VD) - FIXME: Missing from the standard:
- // - an entity with reference type and is initialized with an
- // expression that is value-dependent [C++11]
- if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
- if ((Ctx.getLangOpts().CPlusPlus11 ?
- Var->getType()->isLiteralType(Ctx) :
- Var->getType()->isIntegralOrEnumerationType()) &&
- (Var->getType().isConstQualified() ||
- Var->getType()->isReferenceType())) {
- if (const Expr *Init = Var->getAnyInitializer())
- if (Init->isValueDependent()) {
- ValueDependent = true;
- InstantiationDependent = true;
- }
- }
-
- // (VD) - FIXME: Missing from the standard:
- // - a member function or a static data member of the current
- // instantiation
- if (Var->isStaticDataMember() &&
- Var->getDeclContext()->isDependentContext()) {
- ValueDependent = true;
- InstantiationDependent = true;
- TypeSourceInfo *TInfo = Var->getFirstDecl()->getTypeSourceInfo();
- if (TInfo->getType()->isIncompleteArrayType())
- TypeDependent = true;
- }
-
- return;
- }
-
- // (VD) - FIXME: Missing from the standard:
- // - a member function or a static data member of the current
- // instantiation
- if (isa<CXXMethodDecl>(D) && D->getDeclContext()->isDependentContext()) {
- ValueDependent = true;
- InstantiationDependent = true;
- }
-}
-
-void DeclRefExpr::computeDependence(const ASTContext &Ctx) {
- bool TypeDependent = false;
- bool ValueDependent = false;
- bool InstantiationDependent = false;
- computeDeclRefDependence(Ctx, getDecl(), getType(), TypeDependent,
- ValueDependent, InstantiationDependent);
-
- ExprBits.TypeDependent |= TypeDependent;
- ExprBits.ValueDependent |= ValueDependent;
- ExprBits.InstantiationDependent |= InstantiationDependent;
-
- // Is the declaration a parameter pack?
- if (getDecl()->isParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
-}
-
DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, ValueDecl *D,
bool RefersToEnclosingVariableOrCapture, QualType T,
ExprValueKind VK, SourceLocation L,
const DeclarationNameLoc &LocInfo,
NonOdrUseReason NOUR)
- : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false),
- D(D), DNLoc(LocInfo) {
+ : Expr(DeclRefExprClass, T, VK, OK_Ordinary), D(D), DNLoc(LocInfo) {
DeclRefExprBits.HasQualifier = false;
DeclRefExprBits.HasTemplateKWAndArgsInfo = false;
DeclRefExprBits.HasFoundDecl = false;
@@ -492,7 +388,7 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, ValueDecl *D,
RefersToEnclosingVariableOrCapture;
DeclRefExprBits.NonOdrUseReason = NOUR;
DeclRefExprBits.Loc = L;
- computeDependence(Ctx);
+ setDependence(computeDependence(this, Ctx));
}
DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
@@ -502,19 +398,13 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
const DeclarationNameInfo &NameInfo, NamedDecl *FoundD,
const TemplateArgumentListInfo *TemplateArgs,
QualType T, ExprValueKind VK, NonOdrUseReason NOUR)
- : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false),
- D(D), DNLoc(NameInfo.getInfo()) {
+ : Expr(DeclRefExprClass, T, VK, OK_Ordinary), D(D),
+ DNLoc(NameInfo.getInfo()) {
DeclRefExprBits.Loc = NameInfo.getLoc();
DeclRefExprBits.HasQualifier = QualifierLoc ? 1 : 0;
- if (QualifierLoc) {
+ if (QualifierLoc)
new (getTrailingObjects<NestedNameSpecifierLoc>())
NestedNameSpecifierLoc(QualifierLoc);
- auto *NNS = QualifierLoc.getNestedNameSpecifier();
- if (NNS->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- if (NNS->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
- }
DeclRefExprBits.HasFoundDecl = FoundD ? 1 : 0;
if (FoundD)
*getTrailingObjects<NamedDecl *>() = FoundD;
@@ -524,22 +414,18 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
RefersToEnclosingVariableOrCapture;
DeclRefExprBits.NonOdrUseReason = NOUR;
if (TemplateArgs) {
- bool Dependent = false;
- bool InstantiationDependent = false;
- bool ContainsUnexpandedParameterPack = false;
+ auto Deps = TemplateArgumentDependence::None;
getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
TemplateKWLoc, *TemplateArgs, getTrailingObjects<TemplateArgumentLoc>(),
- Dependent, InstantiationDependent, ContainsUnexpandedParameterPack);
- assert(!Dependent && "built a DeclRefExpr with dependent template args");
- ExprBits.InstantiationDependent |= InstantiationDependent;
- ExprBits.ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack;
+ Deps);
+ assert(!(Deps & TemplateArgumentDependence::Dependent) &&
+ "built a DeclRefExpr with dependent template args");
} else if (TemplateKWLoc.isValid()) {
getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
TemplateKWLoc);
}
DeclRefExprBits.HadMultipleCandidates = 0;
-
- computeDependence(Ctx);
+ setDependence(computeDependence(this, Ctx));
}
DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context,
@@ -611,10 +497,7 @@ SourceLocation DeclRefExpr::getEndLoc() const {
PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
StringLiteral *SL)
- : Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary,
- FNTy->isDependentType(), FNTy->isDependentType(),
- FNTy->isInstantiationDependentType(),
- /*ContainsUnexpandedParameterPack=*/false) {
+ : Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary) {
PredefinedExprBits.Kind = IK;
assert((getIdentKind() == IK) &&
"IdentKind do not fit in PredefinedExprBitfields!");
@@ -623,6 +506,35 @@ PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
PredefinedExprBits.Loc = L;
if (HasFunctionName)
setFunctionName(SL);
+ setDependence(computeDependence(this));
+}
+
+PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FnTy, IdentKind IK,
+ TypeSourceInfo *Info)
+ : Expr(PredefinedExprClass, FnTy, VK_LValue, OK_Ordinary) {
+ PredefinedExprBits.Kind = IK;
+ assert((getIdentKind() == IK) &&
+ "IdentKind do not fit in PredefinedExprBitFields!");
+ assert(IK == UniqueStableNameType &&
+ "Constructor only valid with UniqueStableNameType");
+ PredefinedExprBits.HasFunctionName = false;
+ PredefinedExprBits.Loc = L;
+ setTypeSourceInfo(Info);
+ setDependence(computeDependence(this));
+}
+
+PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FnTy, IdentKind IK,
+ Expr *E)
+ : Expr(PredefinedExprClass, FnTy, VK_LValue, OK_Ordinary) {
+ PredefinedExprBits.Kind = IK;
+ assert((getIdentKind() == IK) &&
+ "IdentKind do not fit in PredefinedExprBitFields!");
+ assert(IK == UniqueStableNameExpr &&
+ "Constructor only valid with UniqueStableNameExpr");
+ PredefinedExprBits.HasFunctionName = false;
+ PredefinedExprBits.Loc = L;
+ setExpr(E);
+ setDependence(computeDependence(this));
}
PredefinedExpr::PredefinedExpr(EmptyShell Empty, bool HasFunctionName)
@@ -634,15 +546,44 @@ PredefinedExpr *PredefinedExpr::Create(const ASTContext &Ctx, SourceLocation L,
QualType FNTy, IdentKind IK,
StringLiteral *SL) {
bool HasFunctionName = SL != nullptr;
- void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *>(HasFunctionName),
- alignof(PredefinedExpr));
+ void *Mem = Ctx.Allocate(
+ totalSizeToAlloc<Stmt *, Expr *, TypeSourceInfo *>(HasFunctionName, 0, 0),
+ alignof(PredefinedExpr));
return new (Mem) PredefinedExpr(L, FNTy, IK, SL);
}
+PredefinedExpr *PredefinedExpr::Create(const ASTContext &Ctx, SourceLocation L,
+ QualType FNTy, IdentKind IK,
+ StringLiteral *SL,
+ TypeSourceInfo *Info) {
+ assert(IK == UniqueStableNameType && "Only valid with UniqueStableNameType");
+ bool HasFunctionName = SL != nullptr;
+ void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *, Expr *, TypeSourceInfo *>(
+ HasFunctionName, 0, !HasFunctionName),
+ alignof(PredefinedExpr));
+ if (HasFunctionName)
+ return new (Mem) PredefinedExpr(L, FNTy, IK, SL);
+ return new (Mem) PredefinedExpr(L, FNTy, IK, Info);
+}
+
+PredefinedExpr *PredefinedExpr::Create(const ASTContext &Ctx, SourceLocation L,
+ QualType FNTy, IdentKind IK,
+ StringLiteral *SL, Expr *E) {
+ assert(IK == UniqueStableNameExpr && "Only valid with UniqueStableNameExpr");
+ bool HasFunctionName = SL != nullptr;
+ void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *, Expr *, TypeSourceInfo *>(
+ HasFunctionName, !HasFunctionName, 0),
+ alignof(PredefinedExpr));
+ if (HasFunctionName)
+ return new (Mem) PredefinedExpr(L, FNTy, IK, SL);
+ return new (Mem) PredefinedExpr(L, FNTy, IK, E);
+}
+
PredefinedExpr *PredefinedExpr::CreateEmpty(const ASTContext &Ctx,
bool HasFunctionName) {
- void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *>(HasFunctionName),
- alignof(PredefinedExpr));
+ void *Mem = Ctx.Allocate(
+ totalSizeToAlloc<Stmt *, Expr *, TypeSourceInfo *>(HasFunctionName, 0, 0),
+ alignof(PredefinedExpr));
return new (Mem) PredefinedExpr(EmptyShell(), HasFunctionName);
}
@@ -662,12 +603,28 @@ StringRef PredefinedExpr::getIdentKindName(PredefinedExpr::IdentKind IK) {
return "__FUNCSIG__";
case LFuncSig:
return "L__FUNCSIG__";
+ case UniqueStableNameType:
+ case UniqueStableNameExpr:
+ return "__builtin_unique_stable_name";
case PrettyFunctionNoVirtual:
break;
}
llvm_unreachable("Unknown ident kind for PredefinedExpr");
}
+std::string PredefinedExpr::ComputeName(ASTContext &Context, IdentKind IK,
+ QualType Ty) {
+ std::unique_ptr<MangleContext> Ctx{ItaniumMangleContext::create(
+ Context, Context.getDiagnostics(), /*IsUniqueNameMangler*/ true)};
+
+ Ty = Ty.getCanonicalType();
+
+ SmallString<256> Buffer;
+ llvm::raw_svector_ostream Out(Buffer);
+ Ctx->mangleTypeName(Ty, Out);
+ return std::string(Buffer.str());
+}
+
// FIXME: Maybe this should use DeclPrinter with a special "print predefined
// expr" policy instead.
std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
@@ -681,18 +638,22 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
if (MC->shouldMangleDeclName(ND)) {
SmallString<256> Buffer;
llvm::raw_svector_ostream Out(Buffer);
+ GlobalDecl GD;
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(ND))
- MC->mangleCXXCtor(CD, Ctor_Base, Out);
+ GD = GlobalDecl(CD, Ctor_Base);
else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(ND))
- MC->mangleCXXDtor(DD, Dtor_Base, Out);
+ GD = GlobalDecl(DD, Dtor_Base);
+ else if (ND->hasAttr<CUDAGlobalAttr>())
+ GD = GlobalDecl(cast<FunctionDecl>(ND));
else
- MC->mangleName(ND, Out);
+ GD = GlobalDecl(ND);
+ MC->mangleName(GD, Out);
if (!Buffer.empty() && Buffer.front() == '\01')
- return Buffer.substr(1);
- return Buffer.str();
+ return std::string(Buffer.substr(1));
+ return std::string(Buffer.str());
} else
- return ND->getIdentifier()->getName();
+ return std::string(ND->getIdentifier()->getName());
}
return "";
}
@@ -711,7 +672,7 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
Out << ComputeName(IK, DCBlock);
else if (auto *DCDecl = dyn_cast<Decl>(DC))
Out << ComputeName(IK, DCDecl) << "_block_invoke";
- return Out.str();
+ return std::string(Out.str());
}
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
if (IK != PrettyFunction && IK != PrettyFunctionNoVirtual &&
@@ -856,7 +817,7 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
Out << Proto;
- return Name.str().str();
+ return std::string(Name);
}
if (const CapturedDecl *CD = dyn_cast<CapturedDecl>(CurrentDecl)) {
for (const DeclContext *DC = CD->getParent(); DC; DC = DC->getParent())
@@ -887,7 +848,7 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
MD->getSelector().print(Out);
Out << ']';
- return Name.str().str();
+ return std::string(Name);
}
if (isa<TranslationUnitDecl>(CurrentDecl) && IK == PrettyFunction) {
// __PRETTY_FUNCTION__ -> "top level", the others produce an empty string.
@@ -915,13 +876,12 @@ void APNumericStorage::setIntValue(const ASTContext &C,
IntegerLiteral::IntegerLiteral(const ASTContext &C, const llvm::APInt &V,
QualType type, SourceLocation l)
- : Expr(IntegerLiteralClass, type, VK_RValue, OK_Ordinary, false, false,
- false, false),
- Loc(l) {
+ : Expr(IntegerLiteralClass, type, VK_RValue, OK_Ordinary), Loc(l) {
assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
assert(V.getBitWidth() == C.getIntWidth(type) &&
"Integer type is not the correct size for constant.");
setValue(C, V);
+ setDependence(ExprDependence::None);
}
IntegerLiteral *
@@ -938,13 +898,13 @@ IntegerLiteral::Create(const ASTContext &C, EmptyShell Empty) {
FixedPointLiteral::FixedPointLiteral(const ASTContext &C, const llvm::APInt &V,
QualType type, SourceLocation l,
unsigned Scale)
- : Expr(FixedPointLiteralClass, type, VK_RValue, OK_Ordinary, false, false,
- false, false),
- Loc(l), Scale(Scale) {
+ : Expr(FixedPointLiteralClass, type, VK_RValue, OK_Ordinary), Loc(l),
+ Scale(Scale) {
assert(type->isFixedPointType() && "Illegal type in FixedPointLiteral");
assert(V.getBitWidth() == C.getTypeInfo(type).Width &&
"Fixed point type is not the correct size for constant.");
setValue(C, V);
+ setDependence(ExprDependence::None);
}
FixedPointLiteral *FixedPointLiteral::CreateFromRawInt(const ASTContext &C,
@@ -955,6 +915,11 @@ FixedPointLiteral *FixedPointLiteral::CreateFromRawInt(const ASTContext &C,
return new (C) FixedPointLiteral(C, V, type, l, Scale);
}
+FixedPointLiteral *FixedPointLiteral::Create(const ASTContext &C,
+ EmptyShell Empty) {
+ return new (C) FixedPointLiteral(Empty);
+}
+
std::string FixedPointLiteral::getValueAsString(unsigned Radix) const {
// Currently the longest decimal number that can be printed is the max for an
// unsigned long _Accum: 4294967295.99999999976716935634613037109375
@@ -962,16 +927,16 @@ std::string FixedPointLiteral::getValueAsString(unsigned Radix) const {
SmallString<64> S;
FixedPointValueToString(
S, llvm::APSInt::getUnsigned(getValue().getZExtValue()), Scale);
- return S.str();
+ return std::string(S.str());
}
FloatingLiteral::FloatingLiteral(const ASTContext &C, const llvm::APFloat &V,
bool isexact, QualType Type, SourceLocation L)
- : Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary, false, false,
- false, false), Loc(L) {
+ : Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary), Loc(L) {
setSemantics(V.getSemantics());
FloatingLiteralBits.IsExact = isexact;
setValue(C, V);
+ setDependence(ExprDependence::None);
}
FloatingLiteral::FloatingLiteral(const ASTContext &C, EmptyShell Empty)
@@ -1031,8 +996,7 @@ StringLiteral::StringLiteral(const ASTContext &Ctx, StringRef Str,
StringKind Kind, bool Pascal, QualType Ty,
const SourceLocation *Loc,
unsigned NumConcatenated)
- : Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false,
- false) {
+ : Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary) {
assert(Ctx.getAsConstantArrayType(Ty) &&
"StringLiteral must be of constant array type!");
unsigned CharByteWidth = mapCharByteWidth(Ctx.getTargetInfo(), Kind);
@@ -1071,6 +1035,8 @@ StringLiteral::StringLiteral(const ASTContext &Ctx, StringRef Str,
// Initialize the trailing array of char holding the string data.
std::memcpy(getTrailingObjects<char>(), Str.data(), ByteLength);
+
+ setDependence(ExprDependence::None);
}
StringLiteral::StringLiteral(EmptyShell Empty, unsigned NumConcatenated,
@@ -1339,10 +1305,7 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs,
ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
SourceLocation RParenLoc, unsigned MinNumArgs,
ADLCallKind UsesADL)
- : Expr(SC, Ty, VK, OK_Ordinary, Fn->isTypeDependent(),
- Fn->isValueDependent(), Fn->isInstantiationDependent(),
- Fn->containsUnexpandedParameterPack()),
- RParenLoc(RParenLoc) {
+ : Expr(SC, Ty, VK, OK_Ordinary), RParenLoc(RParenLoc) {
NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
unsigned NumPreArgs = PreArgs.size();
CallExprBits.NumPreArgs = NumPreArgs;
@@ -1356,17 +1319,14 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs,
CallExprBits.UsesADL = static_cast<bool>(UsesADL);
setCallee(Fn);
- for (unsigned I = 0; I != NumPreArgs; ++I) {
- updateDependenciesFromArg(PreArgs[I]);
+ for (unsigned I = 0; I != NumPreArgs; ++I)
setPreArg(I, PreArgs[I]);
- }
- for (unsigned I = 0; I != Args.size(); ++I) {
- updateDependenciesFromArg(Args[I]);
+ for (unsigned I = 0; I != Args.size(); ++I)
setArg(I, Args[I]);
- }
- for (unsigned I = Args.size(); I != NumArgs; ++I) {
+ for (unsigned I = Args.size(); I != NumArgs; ++I)
setArg(I, nullptr);
- }
+
+ setDependence(computeDependence(this, PreArgs));
}
CallExpr::CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs,
@@ -1400,7 +1360,8 @@ CallExpr *CallExpr::CreateTemporary(void *Mem, Expr *Fn, QualType Ty,
assert(!(reinterpret_cast<uintptr_t>(Mem) % alignof(CallExpr)) &&
"Misaligned memory in CallExpr::CreateTemporary!");
return new (Mem) CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, /*Args=*/{}, Ty,
- VK, RParenLoc, /*MinNumArgs=*/0, UsesADL);
+ VK, RParenLoc,
+ /*MinNumArgs=*/0, UsesADL);
}
CallExpr *CallExpr::CreateEmpty(const ASTContext &Ctx, unsigned NumArgs,
@@ -1429,33 +1390,31 @@ unsigned CallExpr::offsetToTrailingObjects(StmtClass SC) {
}
}
-void CallExpr::updateDependenciesFromArg(Expr *Arg) {
- if (Arg->isTypeDependent())
- ExprBits.TypeDependent = true;
- if (Arg->isValueDependent())
- ExprBits.ValueDependent = true;
- if (Arg->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- if (Arg->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
-}
-
Decl *Expr::getReferencedDeclOfCallee() {
Expr *CEE = IgnoreParenImpCasts();
- while (SubstNonTypeTemplateParmExpr *NTTP
- = dyn_cast<SubstNonTypeTemplateParmExpr>(CEE)) {
- CEE = NTTP->getReplacement()->IgnoreParenCasts();
+ while (SubstNonTypeTemplateParmExpr *NTTP =
+ dyn_cast<SubstNonTypeTemplateParmExpr>(CEE)) {
+ CEE = NTTP->getReplacement()->IgnoreParenImpCasts();
}
// If we're calling a dereference, look at the pointer instead.
- if (BinaryOperator *BO = dyn_cast<BinaryOperator>(CEE)) {
- if (BO->isPtrMemOp())
- CEE = BO->getRHS()->IgnoreParenCasts();
- } else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(CEE)) {
- if (UO->getOpcode() == UO_Deref)
- CEE = UO->getSubExpr()->IgnoreParenCasts();
+ while (true) {
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(CEE)) {
+ if (BO->isPtrMemOp()) {
+ CEE = BO->getRHS()->IgnoreParenImpCasts();
+ continue;
+ }
+ } else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(CEE)) {
+ if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_AddrOf ||
+ UO->getOpcode() == UO_Plus) {
+ CEE = UO->getSubExpr()->IgnoreParenImpCasts();
+ continue;
+ }
+ }
+ break;
}
+
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE))
return DRE->getDecl();
if (MemberExpr *ME = dyn_cast<MemberExpr>(CEE))
@@ -1466,28 +1425,11 @@ Decl *Expr::getReferencedDeclOfCallee() {
return nullptr;
}
-/// getBuiltinCallee - If this is a call to a builtin, return the builtin ID. If
-/// not, return 0.
+/// If this is a call to a builtin, return the builtin ID. If not, return 0.
unsigned CallExpr::getBuiltinCallee() const {
- // All simple function calls (e.g. func()) are implicitly cast to pointer to
- // function. As a result, we try and obtain the DeclRefExpr from the
- // ImplicitCastExpr.
- const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(getCallee());
- if (!ICE) // FIXME: deal with more complex calls (e.g. (func)(), (*func)()).
- return 0;
-
- const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr());
- if (!DRE)
- return 0;
-
- const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
- if (!FDecl)
- return 0;
-
- if (!FDecl->getIdentifier())
- return 0;
-
- return FDecl->getBuiltinID();
+ auto *FDecl =
+ dyn_cast_or_null<FunctionDecl>(getCallee()->getReferencedDeclOfCallee());
+ return FDecl ? FDecl->getBuiltinID() : 0;
}
bool CallExpr::isUnevaluatedBuiltinCall(const ASTContext &Ctx) const {
@@ -1569,28 +1511,17 @@ OffsetOfExpr *OffsetOfExpr::CreateEmpty(const ASTContext &C,
OffsetOfExpr::OffsetOfExpr(const ASTContext &C, QualType type,
SourceLocation OperatorLoc, TypeSourceInfo *tsi,
- ArrayRef<OffsetOfNode> comps, ArrayRef<Expr*> exprs,
+ ArrayRef<OffsetOfNode> comps, ArrayRef<Expr *> exprs,
SourceLocation RParenLoc)
- : Expr(OffsetOfExprClass, type, VK_RValue, OK_Ordinary,
- /*TypeDependent=*/false,
- /*ValueDependent=*/tsi->getType()->isDependentType(),
- tsi->getType()->isInstantiationDependentType(),
- tsi->getType()->containsUnexpandedParameterPack()),
- OperatorLoc(OperatorLoc), RParenLoc(RParenLoc), TSInfo(tsi),
- NumComps(comps.size()), NumExprs(exprs.size())
-{
- for (unsigned i = 0; i != comps.size(); ++i) {
+ : Expr(OffsetOfExprClass, type, VK_RValue, OK_Ordinary),
+ OperatorLoc(OperatorLoc), RParenLoc(RParenLoc), TSInfo(tsi),
+ NumComps(comps.size()), NumExprs(exprs.size()) {
+ for (unsigned i = 0; i != comps.size(); ++i)
setComponent(i, comps[i]);
- }
-
- for (unsigned i = 0; i != exprs.size(); ++i) {
- if (exprs[i]->isTypeDependent() || exprs[i]->isValueDependent())
- ExprBits.ValueDependent = true;
- if (exprs[i]->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
-
+ for (unsigned i = 0; i != exprs.size(); ++i)
setIndexExpr(i, exprs[i]);
- }
+
+ setDependence(computeDependence(this));
}
IdentifierInfo *OffsetOfNode::getFieldName() const {
@@ -1604,39 +1535,15 @@ IdentifierInfo *OffsetOfNode::getFieldName() const {
UnaryExprOrTypeTraitExpr::UnaryExprOrTypeTraitExpr(
UnaryExprOrTypeTrait ExprKind, Expr *E, QualType resultType,
SourceLocation op, SourceLocation rp)
- : Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary,
- false, // Never type-dependent (C++ [temp.dep.expr]p3).
- // Value-dependent if the argument is type-dependent.
- E->isTypeDependent(), E->isInstantiationDependent(),
- E->containsUnexpandedParameterPack()),
+ : Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary),
OpLoc(op), RParenLoc(rp) {
+ assert(ExprKind <= UETT_Last && "invalid enum value!");
UnaryExprOrTypeTraitExprBits.Kind = ExprKind;
+ assert(static_cast<unsigned>(ExprKind) == UnaryExprOrTypeTraitExprBits.Kind &&
+ "UnaryExprOrTypeTraitExprBits.Kind overflow!");
UnaryExprOrTypeTraitExprBits.IsType = false;
Argument.Ex = E;
-
- // Check to see if we are in the situation where alignof(decl) should be
- // dependent because decl's alignment is dependent.
- if (ExprKind == UETT_AlignOf || ExprKind == UETT_PreferredAlignOf) {
- if (!isValueDependent() || !isInstantiationDependent()) {
- E = E->IgnoreParens();
-
- const ValueDecl *D = nullptr;
- if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
- D = DRE->getDecl();
- else if (const auto *ME = dyn_cast<MemberExpr>(E))
- D = ME->getMemberDecl();
-
- if (D) {
- for (const auto *I : D->specific_attrs<AlignedAttr>()) {
- if (I->isAlignmentDependent()) {
- setValueDependent(true);
- setInstantiationDependent(true);
- break;
- }
- }
- }
- }
- }
+ setDependence(computeDependence(this));
}
MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc,
@@ -1644,11 +1551,8 @@ MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc,
const DeclarationNameInfo &NameInfo, QualType T,
ExprValueKind VK, ExprObjectKind OK,
NonOdrUseReason NOUR)
- : Expr(MemberExprClass, T, VK, OK, Base->isTypeDependent(),
- Base->isValueDependent(), Base->isInstantiationDependent(),
- Base->containsUnexpandedParameterPack()),
- Base(Base), MemberDecl(MemberDecl), MemberDNLoc(NameInfo.getInfo()),
- MemberLoc(NameInfo.getLoc()) {
+ : Expr(MemberExprClass, T, VK, OK), Base(Base), MemberDecl(MemberDecl),
+ MemberDNLoc(NameInfo.getInfo()), MemberLoc(NameInfo.getLoc()) {
assert(!NameInfo.getName() ||
MemberDecl->getDeclName() == NameInfo.getName());
MemberExprBits.IsArrow = IsArrow;
@@ -1657,6 +1561,7 @@ MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc,
MemberExprBits.HadMultipleCandidates = false;
MemberExprBits.NonOdrUseReason = NOUR;
MemberExprBits.OperatorLoc = OperatorLoc;
+ setDependence(computeDependence(this));
}
MemberExpr *MemberExpr::Create(
@@ -1678,25 +1583,15 @@ MemberExpr *MemberExpr::Create(
MemberExpr *E = new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, MemberDecl,
NameInfo, T, VK, OK, NOUR);
- if (isa<FieldDecl>(MemberDecl)) {
- DeclContext *DC = MemberDecl->getDeclContext();
- // dyn_cast_or_null is used to handle objC variables which do not
- // have a declaration context.
- CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(DC);
- if (RD && RD->isDependentContext() && RD->isCurrentInstantiation(DC))
- E->setTypeDependent(T->isDependentType());
- }
-
+ // FIXME: remove remaining dependence computation to computeDependence().
+ auto Deps = E->getDependence();
if (HasQualOrFound) {
// FIXME: Wrong. We should be looking at the member declaration we found.
- if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()->isDependent()) {
- E->setValueDependent(true);
- E->setTypeDependent(true);
- E->setInstantiationDependent(true);
- }
+ if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()->isDependent())
+ Deps |= ExprDependence::TypeValueInstantiation;
else if (QualifierLoc &&
QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())
- E->setInstantiationDependent(true);
+ Deps |= ExprDependence::Instantiation;
E->MemberExprBits.HasQualifierOrFoundDecl = true;
@@ -1710,19 +1605,17 @@ MemberExpr *MemberExpr::Create(
TemplateArgs || TemplateKWLoc.isValid();
if (TemplateArgs) {
- bool Dependent = false;
- bool InstantiationDependent = false;
- bool ContainsUnexpandedParameterPack = false;
+ auto TemplateArgDeps = TemplateArgumentDependence::None;
E->getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
TemplateKWLoc, *TemplateArgs,
- E->getTrailingObjects<TemplateArgumentLoc>(), Dependent,
- InstantiationDependent, ContainsUnexpandedParameterPack);
- if (InstantiationDependent)
- E->setInstantiationDependent(true);
+ E->getTrailingObjects<TemplateArgumentLoc>(), TemplateArgDeps);
+ if (TemplateArgDeps & TemplateArgumentDependence::Instantiation)
+ Deps |= ExprDependence::Instantiation;
} else if (TemplateKWLoc.isValid()) {
E->getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
TemplateKWLoc);
}
+ E->setDependence(Deps);
return E;
}
@@ -1823,12 +1716,13 @@ bool CastExpr::CastConsistency() const {
auto Ty = getType();
auto SETy = getSubExpr()->getType();
assert(getValueKindForType(Ty) == Expr::getValueKindForType(SETy));
- if (isRValue()) {
+ if (isRValue() && !Ty->isDependentType() && !SETy->isDependentType()) {
Ty = Ty->getPointeeType();
SETy = SETy->getPointeeType();
}
- assert(!Ty.isNull() && !SETy.isNull() &&
- Ty.getAddressSpace() != SETy.getAddressSpace());
+ assert((Ty->isDependentType() || SETy->isDependentType()) ||
+ (!Ty.isNull() && !SETy.isNull() &&
+ Ty.getAddressSpace() != SETy.getAddressSpace()));
goto CheckNoBasePath;
}
// These should not have an inheritance path.
@@ -2163,9 +2057,10 @@ SourceLocExpr::SourceLocExpr(const ASTContext &Ctx, IdentKind Kind,
SourceLocation BLoc, SourceLocation RParenLoc,
DeclContext *ParentContext)
: Expr(SourceLocExprClass, getDecayedSourceLocExprType(Ctx, Kind),
- VK_RValue, OK_Ordinary, false, false, false, false),
+ VK_RValue, OK_Ordinary),
BuiltinLoc(BLoc), RParenLoc(RParenLoc), ParentContext(ParentContext) {
SourceLocExprBits.Kind = Kind;
+ setDependence(ExprDependence::None);
}
StringRef SourceLocExpr::getBuiltinStr() const {
@@ -2229,25 +2124,14 @@ APValue SourceLocExpr::EvaluateInContext(const ASTContext &Ctx,
}
InitListExpr::InitListExpr(const ASTContext &C, SourceLocation lbraceloc,
- ArrayRef<Expr*> initExprs, SourceLocation rbraceloc)
- : Expr(InitListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false,
- false, false),
- InitExprs(C, initExprs.size()),
- LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), AltForm(nullptr, true)
-{
+ ArrayRef<Expr *> initExprs, SourceLocation rbraceloc)
+ : Expr(InitListExprClass, QualType(), VK_RValue, OK_Ordinary),
+ InitExprs(C, initExprs.size()), LBraceLoc(lbraceloc),
+ RBraceLoc(rbraceloc), AltForm(nullptr, true) {
sawArrayRangeDesignator(false);
- for (unsigned I = 0; I != initExprs.size(); ++I) {
- if (initExprs[I]->isTypeDependent())
- ExprBits.TypeDependent = true;
- if (initExprs[I]->isValueDependent())
- ExprBits.ValueDependent = true;
- if (initExprs[I]->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- if (initExprs[I]->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
- }
-
InitExprs.insert(C, InitExprs.end(), initExprs.begin(), initExprs.end());
+
+ setDependence(computeDependence(this));
}
void InitListExpr::reserveInits(const ASTContext &C, unsigned NumInits) {
@@ -2388,6 +2272,64 @@ Stmt *BlockExpr::getBody() {
// Generic Expression Routines
//===----------------------------------------------------------------------===//
+bool Expr::isReadIfDiscardedInCPlusPlus11() const {
+ // In C++11, discarded-value expressions of a certain form are special,
+ // according to [expr]p10:
+ // The lvalue-to-rvalue conversion (4.1) is applied only if the
+ // expression is an lvalue of volatile-qualified type and it has
+ // one of the following forms:
+ if (!isGLValue() || !getType().isVolatileQualified())
+ return false;
+
+ const Expr *E = IgnoreParens();
+
+ // - id-expression (5.1.1),
+ if (isa<DeclRefExpr>(E))
+ return true;
+
+ // - subscripting (5.2.1),
+ if (isa<ArraySubscriptExpr>(E))
+ return true;
+
+ // - class member access (5.2.5),
+ if (isa<MemberExpr>(E))
+ return true;
+
+ // - indirection (5.3.1),
+ if (auto *UO = dyn_cast<UnaryOperator>(E))
+ if (UO->getOpcode() == UO_Deref)
+ return true;
+
+ if (auto *BO = dyn_cast<BinaryOperator>(E)) {
+ // - pointer-to-member operation (5.5),
+ if (BO->isPtrMemOp())
+ return true;
+
+ // - comma expression (5.18) where the right operand is one of the above.
+ if (BO->getOpcode() == BO_Comma)
+ return BO->getRHS()->isReadIfDiscardedInCPlusPlus11();
+ }
+
+ // - conditional expression (5.16) where both the second and the third
+ // operands are one of the above, or
+ if (auto *CO = dyn_cast<ConditionalOperator>(E))
+ return CO->getTrueExpr()->isReadIfDiscardedInCPlusPlus11() &&
+ CO->getFalseExpr()->isReadIfDiscardedInCPlusPlus11();
+ // The related edge case of "*x ?: *x".
+ if (auto *BCO =
+ dyn_cast<BinaryConditionalOperator>(E)) {
+ if (auto *OVE = dyn_cast<OpaqueValueExpr>(BCO->getTrueExpr()))
+ return OVE->getSourceExpr()->isReadIfDiscardedInCPlusPlus11() &&
+ BCO->getFalseExpr()->isReadIfDiscardedInCPlusPlus11();
+ }
+
+ // Objective-C++ extensions to the rule.
+ if (isa<PseudoObjectExpr>(E) || isa<ObjCIvarRefExpr>(E))
+ return true;
+
+ return false;
+}
+
/// isUnusedResultAWarning - Return true if this immediate expression should
/// be warned about if the result is unused. If so, fill in Loc and Ranges
/// with location to warn on and the source range[s] to report with the
@@ -2576,6 +2518,7 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
// If we don't know precisely what we're looking at, let's not warn.
case UnresolvedLookupExprClass:
case CXXUnresolvedConstructExprClass:
+ case RecoveryExprClass:
return false;
case CXXTemporaryObjectExprClass:
@@ -2675,20 +2618,31 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
}
case CXXFunctionalCastExprClass:
case CStyleCastExprClass: {
- // Ignore an explicit cast to void unless the operand is a non-trivial
- // volatile lvalue.
+ // Ignore an explicit cast to void, except in C++98 if the operand is a
+ // volatile glvalue for which we would trigger an implicit read in any
+ // other language mode. (Such an implicit read always happens as part of
+ // the lvalue conversion in C, and happens in C++ for expressions of all
+ // forms where it seems likely the user intended to trigger a volatile
+ // load.)
const CastExpr *CE = cast<CastExpr>(this);
+ const Expr *SubE = CE->getSubExpr()->IgnoreParens();
if (CE->getCastKind() == CK_ToVoid) {
- if (CE->getSubExpr()->isGLValue() &&
- CE->getSubExpr()->getType().isVolatileQualified()) {
- const DeclRefExpr *DRE =
- dyn_cast<DeclRefExpr>(CE->getSubExpr()->IgnoreParens());
- if (!(DRE && isa<VarDecl>(DRE->getDecl()) &&
- cast<VarDecl>(DRE->getDecl())->hasLocalStorage()) &&
- !isa<CallExpr>(CE->getSubExpr()->IgnoreParens())) {
- return CE->getSubExpr()->isUnusedResultAWarning(WarnE, Loc,
- R1, R2, Ctx);
- }
+ if (Ctx.getLangOpts().CPlusPlus && !Ctx.getLangOpts().CPlusPlus11 &&
+ SubE->isReadIfDiscardedInCPlusPlus11()) {
+ // Suppress the "unused value" warning for idiomatic usage of
+ // '(void)var;' used to suppress "unused variable" warnings.
+ if (auto *DRE = dyn_cast<DeclRefExpr>(SubE))
+ if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
+ if (!VD->isExternallyVisible())
+ return false;
+
+ // The lvalue-to-rvalue conversion would have no effect for an array.
+ // It's implausible that the programmer expected this to result in a
+ // volatile array load, so don't warn.
+ if (SubE->getType()->isArrayType())
+ return false;
+
+ return SubE->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
}
return false;
}
@@ -2900,6 +2854,12 @@ static Expr *IgnoreImplicitAsWrittenSingleStep(Expr *E) {
return IgnoreImplicitSingleStep(E);
}
+static Expr *IgnoreParensOnlySingleStep(Expr *E) {
+ if (auto *PE = dyn_cast<ParenExpr>(E))
+ return PE->getSubExpr();
+ return E;
+}
+
static Expr *IgnoreParensSingleStep(Expr *E) {
if (auto *PE = dyn_cast<ParenExpr>(E))
return PE->getSubExpr();
@@ -2919,9 +2879,6 @@ static Expr *IgnoreParensSingleStep(Expr *E) {
return CE->getChosenSubExpr();
}
- else if (auto *CE = dyn_cast<ConstantExpr>(E))
- return CE->getSubExpr();
-
return E;
}
@@ -3026,12 +2983,16 @@ Expr *Expr::IgnoreUnlessSpelledInSource() {
Expr *LastE = nullptr;
while (E != LastE) {
LastE = E;
- E = E->IgnoreParenImpCasts();
+ E = IgnoreExprNodes(E, IgnoreImplicitSingleStep,
+ IgnoreImpCastsExtraSingleStep,
+ IgnoreParensOnlySingleStep);
auto SR = E->getSourceRange();
if (auto *C = dyn_cast<CXXConstructExpr>(E)) {
- if (C->getNumArgs() == 1) {
+ auto NumArgs = C->getNumArgs();
+ if (NumArgs == 1 ||
+ (NumArgs > 1 && isa<CXXDefaultArgExpr>(C->getArg(1)))) {
Expr *A = C->getArg(0);
if (A->getSourceRange() == SR || !isa<CXXTemporaryObjectExpr>(C))
E = A;
@@ -3039,7 +3000,18 @@ Expr *Expr::IgnoreUnlessSpelledInSource() {
}
if (auto *C = dyn_cast<CXXMemberCallExpr>(E)) {
- Expr *ExprNode = C->getImplicitObjectArgument()->IgnoreParenImpCasts();
+ Expr *ExprNode = C->getImplicitObjectArgument();
+ if (ExprNode->getSourceRange() == SR) {
+ E = ExprNode;
+ continue;
+ }
+ if (auto *PE = dyn_cast<ParenExpr>(ExprNode)) {
+ if (PE->getSourceRange() == C->getSourceRange()) {
+ E = PE;
+ continue;
+ }
+ }
+ ExprNode = ExprNode->IgnoreParenImpCasts();
if (ExprNode->getSourceRange() == SR)
E = ExprNode;
}
@@ -3206,6 +3178,9 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
switch (getStmtClass()) {
default: break;
+ case Stmt::ExprWithCleanupsClass:
+ return cast<ExprWithCleanups>(this)->getSubExpr()->isConstantInitializer(
+ Ctx, IsForRef, Culprit);
case StringLiteralClass:
case ObjCEncodeExprClass:
return true;
@@ -3319,6 +3294,7 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
case ObjCBridgedCastExprClass:
case CXXDynamicCastExprClass:
case CXXReinterpretCastExprClass:
+ case CXXAddrspaceCastExprClass:
case CXXConstCastExprClass: {
const CastExpr *CE = cast<CastExpr>(this);
@@ -3385,6 +3361,26 @@ namespace {
bool hasSideEffects() const { return HasSideEffects; }
+ void VisitDecl(const Decl *D) {
+ if (!D)
+ return;
+
+ // We assume the caller checks subexpressions (eg, the initializer, VLA
+ // bounds) for side-effects on our behalf.
+ if (auto *VD = dyn_cast<VarDecl>(D)) {
+ // Registering a destructor is a side-effect.
+ if (IncludePossibleEffects && VD->isThisDeclarationADefinition() &&
+ VD->needsDestruction(Context))
+ HasSideEffects = true;
+ }
+ }
+
+ void VisitDeclStmt(const DeclStmt *DS) {
+ for (auto *D : DS->decls())
+ VisitDecl(D);
+ Inherited::VisitDeclStmt(DS);
+ }
+
void VisitExpr(const Expr *E) {
if (!HasSideEffects &&
E->HasSideEffects(Context, IncludePossibleEffects))
@@ -3421,6 +3417,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case SubstNonTypeTemplateParmPackExprClass:
case FunctionParmPackExprClass:
case TypoExprClass:
+ case RecoveryExprClass:
case CXXFoldExprClass:
llvm_unreachable("shouldn't see dependent / unresolved nodes here");
@@ -3457,6 +3454,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case OpaqueValueExprClass:
case SourceLocExprClass:
case ConceptSpecializationExprClass:
+ case RequiresExprClass:
// These never have a side-effect.
return false;
@@ -3515,7 +3513,10 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case ParenExprClass:
case ArraySubscriptExprClass:
+ case MatrixSubscriptExprClass:
case OMPArraySectionExprClass:
+ case OMPArrayShapingExprClass:
+ case OMPIteratorExprClass:
case MemberExprClass:
case ConditionalOperatorClass:
case BinaryConditionalOperatorClass:
@@ -3586,6 +3587,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case CXXStaticCastExprClass:
case CXXReinterpretCastExprClass:
case CXXConstCastExprClass:
+ case CXXAddrspaceCastExprClass:
case CXXFunctionalCastExprClass:
case BuiltinBitCastExprClass: {
// While volatile reads are side-effecting in both C and C++, we treat them
@@ -3627,7 +3629,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case LambdaExprClass: {
const LambdaExpr *LE = cast<LambdaExpr>(this);
for (Expr *E : LE->capture_inits())
- if (E->HasSideEffects(Ctx, IncludePossibleEffects))
+ if (E && E->HasSideEffects(Ctx, IncludePossibleEffects))
return true;
return false;
}
@@ -3810,6 +3812,11 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
return Source->isNullPointerConstant(Ctx, NPC);
}
+ // If the expression has no type information, it cannot be a null pointer
+ // constant.
+ if (getType().isNull())
+ return NPCK_NotNull;
+
// C++11 nullptr_t is always a null pointer constant.
if (getType()->isNullPtrType())
return NPCK_CXX11_nullptr;
@@ -4148,28 +4155,16 @@ void ExtVectorElementExpr::getEncodedElementAccess(
}
}
-ShuffleVectorExpr::ShuffleVectorExpr(const ASTContext &C, ArrayRef<Expr*> args,
+ShuffleVectorExpr::ShuffleVectorExpr(const ASTContext &C, ArrayRef<Expr *> args,
QualType Type, SourceLocation BLoc,
SourceLocation RP)
- : Expr(ShuffleVectorExprClass, Type, VK_RValue, OK_Ordinary,
- Type->isDependentType(), Type->isDependentType(),
- Type->isInstantiationDependentType(),
- Type->containsUnexpandedParameterPack()),
- BuiltinLoc(BLoc), RParenLoc(RP), NumExprs(args.size())
-{
+ : Expr(ShuffleVectorExprClass, Type, VK_RValue, OK_Ordinary),
+ BuiltinLoc(BLoc), RParenLoc(RP), NumExprs(args.size()) {
SubExprs = new (C) Stmt*[args.size()];
- for (unsigned i = 0; i != args.size(); i++) {
- if (args[i]->isTypeDependent())
- ExprBits.TypeDependent = true;
- if (args[i]->isValueDependent())
- ExprBits.ValueDependent = true;
- if (args[i]->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- if (args[i]->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
-
+ for (unsigned i = 0; i != args.size(); i++)
SubExprs[i] = args[i];
- }
+
+ setDependence(computeDependence(this));
}
void ShuffleVectorExpr::setExprs(const ASTContext &C, ArrayRef<Expr *> Exprs) {
@@ -4187,11 +4182,7 @@ GenericSelectionExpr::GenericSelectionExpr(
bool ContainsUnexpandedParameterPack, unsigned ResultIndex)
: Expr(GenericSelectionExprClass, AssocExprs[ResultIndex]->getType(),
AssocExprs[ResultIndex]->getValueKind(),
- AssocExprs[ResultIndex]->getObjectKind(),
- AssocExprs[ResultIndex]->isTypeDependent(),
- AssocExprs[ResultIndex]->isValueDependent(),
- AssocExprs[ResultIndex]->isInstantiationDependent(),
- ContainsUnexpandedParameterPack),
+ AssocExprs[ResultIndex]->getObjectKind()),
NumAssocs(AssocExprs.size()), ResultIndex(ResultIndex),
DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) {
assert(AssocTypes.size() == AssocExprs.size() &&
@@ -4205,6 +4196,8 @@ GenericSelectionExpr::GenericSelectionExpr(
getTrailingObjects<Stmt *>() + AssocExprStartIndex);
std::copy(AssocTypes.begin(), AssocTypes.end(),
getTrailingObjects<TypeSourceInfo *>());
+
+ setDependence(computeDependence(this, ContainsUnexpandedParameterPack));
}
GenericSelectionExpr::GenericSelectionExpr(
@@ -4213,10 +4206,7 @@ GenericSelectionExpr::GenericSelectionExpr(
SourceLocation DefaultLoc, SourceLocation RParenLoc,
bool ContainsUnexpandedParameterPack)
: Expr(GenericSelectionExprClass, Context.DependentTy, VK_RValue,
- OK_Ordinary,
- /*isTypeDependent=*/true,
- /*isValueDependent=*/true,
- /*isInstantiationDependent=*/true, ContainsUnexpandedParameterPack),
+ OK_Ordinary),
NumAssocs(AssocExprs.size()), ResultIndex(ResultDependentIndex),
DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) {
assert(AssocTypes.size() == AssocExprs.size() &&
@@ -4229,6 +4219,8 @@ GenericSelectionExpr::GenericSelectionExpr(
getTrailingObjects<Stmt *>() + AssocExprStartIndex);
std::copy(AssocTypes.begin(), AssocTypes.end(),
getTrailingObjects<TypeSourceInfo *>());
+
+ setDependence(computeDependence(this, ContainsUnexpandedParameterPack));
}
GenericSelectionExpr::GenericSelectionExpr(EmptyShell Empty, unsigned NumAssocs)
@@ -4287,15 +4279,11 @@ DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty,
llvm::ArrayRef<Designator> Designators,
SourceLocation EqualOrColonLoc,
bool GNUSyntax,
- ArrayRef<Expr*> IndexExprs,
- Expr *Init)
- : Expr(DesignatedInitExprClass, Ty,
- Init->getValueKind(), Init->getObjectKind(),
- Init->isTypeDependent(), Init->isValueDependent(),
- Init->isInstantiationDependent(),
- Init->containsUnexpandedParameterPack()),
- EqualOrColonLoc(EqualOrColonLoc), GNUSyntax(GNUSyntax),
- NumDesignators(Designators.size()), NumSubExprs(IndexExprs.size() + 1) {
+ ArrayRef<Expr *> IndexExprs, Expr *Init)
+ : Expr(DesignatedInitExprClass, Ty, Init->getValueKind(),
+ Init->getObjectKind()),
+ EqualOrColonLoc(EqualOrColonLoc), GNUSyntax(GNUSyntax),
+ NumDesignators(Designators.size()), NumSubExprs(IndexExprs.size() + 1) {
this->Designators = new (C) Designator[NumDesignators];
// Record the initializer itself.
@@ -4307,38 +4295,10 @@ DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty,
unsigned IndexIdx = 0;
for (unsigned I = 0; I != NumDesignators; ++I) {
this->Designators[I] = Designators[I];
-
if (this->Designators[I].isArrayDesignator()) {
- // Compute type- and value-dependence.
- Expr *Index = IndexExprs[IndexIdx];
- if (Index->isTypeDependent() || Index->isValueDependent())
- ExprBits.TypeDependent = ExprBits.ValueDependent = true;
- if (Index->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- // Propagate unexpanded parameter packs.
- if (Index->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
-
// Copy the index expressions into permanent storage.
*Child++ = IndexExprs[IndexIdx++];
} else if (this->Designators[I].isArrayRangeDesignator()) {
- // Compute type- and value-dependence.
- Expr *Start = IndexExprs[IndexIdx];
- Expr *End = IndexExprs[IndexIdx + 1];
- if (Start->isTypeDependent() || Start->isValueDependent() ||
- End->isTypeDependent() || End->isValueDependent()) {
- ExprBits.TypeDependent = ExprBits.ValueDependent = true;
- ExprBits.InstantiationDependent = true;
- } else if (Start->isInstantiationDependent() ||
- End->isInstantiationDependent()) {
- ExprBits.InstantiationDependent = true;
- }
-
- // Propagate unexpanded parameter packs.
- if (Start->containsUnexpandedParameterPack() ||
- End->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
-
// Copy the start/end expressions into permanent storage.
*Child++ = IndexExprs[IndexIdx++];
*Child++ = IndexExprs[IndexIdx++];
@@ -4346,6 +4306,7 @@ DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty,
}
assert(IndexIdx == IndexExprs.size() && "Wrong number of index expressions");
+ setDependence(computeDependence(this));
}
DesignatedInitExpr *
@@ -4449,14 +4410,19 @@ void DesignatedInitExpr::ExpandDesignator(const ASTContext &C, unsigned Idx,
}
DesignatedInitUpdateExpr::DesignatedInitUpdateExpr(const ASTContext &C,
- SourceLocation lBraceLoc, Expr *baseExpr, SourceLocation rBraceLoc)
- : Expr(DesignatedInitUpdateExprClass, baseExpr->getType(), VK_RValue,
- OK_Ordinary, false, false, false, false) {
+ SourceLocation lBraceLoc,
+ Expr *baseExpr,
+ SourceLocation rBraceLoc)
+ : Expr(DesignatedInitUpdateExprClass, baseExpr->getType(), VK_RValue,
+ OK_Ordinary) {
BaseAndUpdaterExprs[0] = baseExpr;
InitListExpr *ILE = new (C) InitListExpr(C, lBraceLoc, None, rBraceLoc);
ILE->setType(baseExpr->getType());
BaseAndUpdaterExprs[1] = ILE;
+
+ // FIXME: this is wrong, set it correctly.
+ setDependence(ExprDependence::None);
}
SourceLocation DesignatedInitUpdateExpr::getBeginLoc() const {
@@ -4469,23 +4435,13 @@ SourceLocation DesignatedInitUpdateExpr::getEndLoc() const {
ParenListExpr::ParenListExpr(SourceLocation LParenLoc, ArrayRef<Expr *> Exprs,
SourceLocation RParenLoc)
- : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false,
- false, false),
+ : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary),
LParenLoc(LParenLoc), RParenLoc(RParenLoc) {
ParenListExprBits.NumExprs = Exprs.size();
- for (unsigned I = 0, N = Exprs.size(); I != N; ++I) {
- if (Exprs[I]->isTypeDependent())
- ExprBits.TypeDependent = true;
- if (Exprs[I]->isValueDependent())
- ExprBits.ValueDependent = true;
- if (Exprs[I]->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- if (Exprs[I]->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
-
+ for (unsigned I = 0, N = Exprs.size(); I != N; ++I)
getTrailingObjects<Stmt *>()[I] = Exprs[I];
- }
+ setDependence(computeDependence(this));
}
ParenListExpr::ParenListExpr(EmptyShell Empty, unsigned NumExprs)
@@ -4509,6 +4465,115 @@ ParenListExpr *ParenListExpr::CreateEmpty(const ASTContext &Ctx,
return new (Mem) ParenListExpr(EmptyShell(), NumExprs);
}
+BinaryOperator::BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
+ Opcode opc, QualType ResTy, ExprValueKind VK,
+ ExprObjectKind OK, SourceLocation opLoc,
+ FPOptionsOverride FPFeatures)
+ : Expr(BinaryOperatorClass, ResTy, VK, OK) {
+ BinaryOperatorBits.Opc = opc;
+ assert(!isCompoundAssignmentOp() &&
+ "Use CompoundAssignOperator for compound assignments");
+ BinaryOperatorBits.OpLoc = opLoc;
+ SubExprs[LHS] = lhs;
+ SubExprs[RHS] = rhs;
+ BinaryOperatorBits.HasFPFeatures = FPFeatures.requiresTrailingStorage();
+ if (BinaryOperatorBits.HasFPFeatures)
+ *getTrailingFPFeatures() = FPFeatures;
+ setDependence(computeDependence(this));
+}
+
+BinaryOperator::BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
+ Opcode opc, QualType ResTy, ExprValueKind VK,
+ ExprObjectKind OK, SourceLocation opLoc,
+ FPOptionsOverride FPFeatures, bool dead2)
+ : Expr(CompoundAssignOperatorClass, ResTy, VK, OK) {
+ BinaryOperatorBits.Opc = opc;
+ assert(isCompoundAssignmentOp() &&
+ "Use CompoundAssignOperator for compound assignments");
+ BinaryOperatorBits.OpLoc = opLoc;
+ SubExprs[LHS] = lhs;
+ SubExprs[RHS] = rhs;
+ BinaryOperatorBits.HasFPFeatures = FPFeatures.requiresTrailingStorage();
+ if (BinaryOperatorBits.HasFPFeatures)
+ *getTrailingFPFeatures() = FPFeatures;
+ setDependence(computeDependence(this));
+}
+
+BinaryOperator *BinaryOperator::CreateEmpty(const ASTContext &C,
+ bool HasFPFeatures) {
+ unsigned Extra = sizeOfTrailingObjects(HasFPFeatures);
+ void *Mem =
+ C.Allocate(sizeof(BinaryOperator) + Extra, alignof(BinaryOperator));
+ return new (Mem) BinaryOperator(EmptyShell());
+}
+
+BinaryOperator *BinaryOperator::Create(const ASTContext &C, Expr *lhs,
+ Expr *rhs, Opcode opc, QualType ResTy,
+ ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation opLoc,
+ FPOptionsOverride FPFeatures) {
+ bool HasFPFeatures = FPFeatures.requiresTrailingStorage();
+ unsigned Extra = sizeOfTrailingObjects(HasFPFeatures);
+ void *Mem =
+ C.Allocate(sizeof(BinaryOperator) + Extra, alignof(BinaryOperator));
+ return new (Mem)
+ BinaryOperator(C, lhs, rhs, opc, ResTy, VK, OK, opLoc, FPFeatures);
+}
+
+CompoundAssignOperator *
+CompoundAssignOperator::CreateEmpty(const ASTContext &C, bool HasFPFeatures) {
+ unsigned Extra = sizeOfTrailingObjects(HasFPFeatures);
+ void *Mem = C.Allocate(sizeof(CompoundAssignOperator) + Extra,
+ alignof(CompoundAssignOperator));
+ return new (Mem) CompoundAssignOperator(C, EmptyShell(), HasFPFeatures);
+}
+
+CompoundAssignOperator *
+CompoundAssignOperator::Create(const ASTContext &C, Expr *lhs, Expr *rhs,
+ Opcode opc, QualType ResTy, ExprValueKind VK,
+ ExprObjectKind OK, SourceLocation opLoc,
+ FPOptionsOverride FPFeatures,
+ QualType CompLHSType, QualType CompResultType) {
+ bool HasFPFeatures = FPFeatures.requiresTrailingStorage();
+ unsigned Extra = sizeOfTrailingObjects(HasFPFeatures);
+ void *Mem = C.Allocate(sizeof(CompoundAssignOperator) + Extra,
+ alignof(CompoundAssignOperator));
+ return new (Mem)
+ CompoundAssignOperator(C, lhs, rhs, opc, ResTy, VK, OK, opLoc, FPFeatures,
+ CompLHSType, CompResultType);
+}
+
+UnaryOperator *UnaryOperator::CreateEmpty(const ASTContext &C,
+ bool hasFPFeatures) {
+ void *Mem = C.Allocate(totalSizeToAlloc<FPOptionsOverride>(hasFPFeatures),
+ alignof(UnaryOperator));
+ return new (Mem) UnaryOperator(hasFPFeatures, EmptyShell());
+}
+
+UnaryOperator::UnaryOperator(const ASTContext &Ctx, Expr *input, Opcode opc,
+ QualType type, ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation l, bool CanOverflow,
+ FPOptionsOverride FPFeatures)
+ : Expr(UnaryOperatorClass, type, VK, OK), Val(input) {
+ UnaryOperatorBits.Opc = opc;
+ UnaryOperatorBits.CanOverflow = CanOverflow;
+ UnaryOperatorBits.Loc = l;
+ UnaryOperatorBits.HasFPFeatures = FPFeatures.requiresTrailingStorage();
+ setDependence(computeDependence(this));
+}
+
+UnaryOperator *UnaryOperator::Create(const ASTContext &C, Expr *input,
+ Opcode opc, QualType type,
+ ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation l, bool CanOverflow,
+ FPOptionsOverride FPFeatures) {
+ bool HasFPFeatures = FPFeatures.requiresTrailingStorage();
+ unsigned Size = totalSizeToAlloc<FPOptionsOverride>(HasFPFeatures);
+ void *Mem = C.Allocate(Size, alignof(UnaryOperator));
+ return new (Mem)
+ UnaryOperator(C, input, opc, type, VK, OK, l, CanOverflow, FPFeatures);
+}
+
const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) {
if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(e))
e = ewc->getSubExpr();
@@ -4559,10 +4624,9 @@ PseudoObjectExpr *PseudoObjectExpr::Create(const ASTContext &C, Expr *syntax,
}
PseudoObjectExpr::PseudoObjectExpr(QualType type, ExprValueKind VK,
- Expr *syntax, ArrayRef<Expr*> semantics,
+ Expr *syntax, ArrayRef<Expr *> semantics,
unsigned resultIndex)
- : Expr(PseudoObjectExprClass, type, VK, OK_Ordinary,
- /*filled in at end of ctor*/ false, false, false, false) {
+ : Expr(PseudoObjectExprClass, type, VK, OK_Ordinary) {
PseudoObjectExprBits.NumSubExprs = semantics.size() + 1;
PseudoObjectExprBits.ResultIndex = resultIndex + 1;
@@ -4570,20 +4634,13 @@ PseudoObjectExpr::PseudoObjectExpr(QualType type, ExprValueKind VK,
Expr *E = (i == 0 ? syntax : semantics[i-1]);
getSubExprsBuffer()[i] = E;
- if (E->isTypeDependent())
- ExprBits.TypeDependent = true;
- if (E->isValueDependent())
- ExprBits.ValueDependent = true;
- if (E->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- if (E->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
-
if (isa<OpaqueValueExpr>(E))
assert(cast<OpaqueValueExpr>(E)->getSourceExpr() != nullptr &&
"opaque-value semantic expressions for pseudo-object "
"operations must have sources");
}
+
+ setDependence(computeDependence(this));
}
//===----------------------------------------------------------------------===//
@@ -4610,25 +4667,14 @@ Stmt::const_child_range UnaryExprOrTypeTraitExpr::children() const {
return const_child_range(&Argument.Ex, &Argument.Ex + 1);
}
-AtomicExpr::AtomicExpr(SourceLocation BLoc, ArrayRef<Expr*> args,
- QualType t, AtomicOp op, SourceLocation RP)
- : Expr(AtomicExprClass, t, VK_RValue, OK_Ordinary,
- false, false, false, false),
- NumSubExprs(args.size()), BuiltinLoc(BLoc), RParenLoc(RP), Op(op)
-{
+AtomicExpr::AtomicExpr(SourceLocation BLoc, ArrayRef<Expr *> args, QualType t,
+ AtomicOp op, SourceLocation RP)
+ : Expr(AtomicExprClass, t, VK_RValue, OK_Ordinary),
+ NumSubExprs(args.size()), BuiltinLoc(BLoc), RParenLoc(RP), Op(op) {
assert(args.size() == getNumSubExprs(op) && "wrong number of subexpressions");
- for (unsigned i = 0; i != args.size(); i++) {
- if (args[i]->isTypeDependent())
- ExprBits.TypeDependent = true;
- if (args[i]->isValueDependent())
- ExprBits.ValueDependent = true;
- if (args[i]->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- if (args[i]->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
-
+ for (unsigned i = 0; i != args.size(); i++)
SubExprs[i] = args[i];
- }
+ setDependence(computeDependence(this));
}
unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {
@@ -4730,3 +4776,211 @@ QualType OMPArraySectionExpr::getBaseOriginalType(const Expr *Base) {
}
return OriginalTy;
}
+
+RecoveryExpr::RecoveryExpr(ASTContext &Ctx, QualType T, SourceLocation BeginLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> SubExprs)
+ : Expr(RecoveryExprClass, T.getNonReferenceType(),
+ T->isDependentType() ? VK_LValue : getValueKindForType(T),
+ OK_Ordinary),
+ BeginLoc(BeginLoc), EndLoc(EndLoc), NumExprs(SubExprs.size()) {
+ assert(!T.isNull());
+ assert(llvm::all_of(SubExprs, [](Expr* E) { return E != nullptr; }));
+
+ llvm::copy(SubExprs, getTrailingObjects<Expr *>());
+ setDependence(computeDependence(this));
+}
+
+RecoveryExpr *RecoveryExpr::Create(ASTContext &Ctx, QualType T,
+ SourceLocation BeginLoc,
+ SourceLocation EndLoc,
+ ArrayRef<Expr *> SubExprs) {
+ void *Mem = Ctx.Allocate(totalSizeToAlloc<Expr *>(SubExprs.size()),
+ alignof(RecoveryExpr));
+ return new (Mem) RecoveryExpr(Ctx, T, BeginLoc, EndLoc, SubExprs);
+}
+
+RecoveryExpr *RecoveryExpr::CreateEmpty(ASTContext &Ctx, unsigned NumSubExprs) {
+ void *Mem = Ctx.Allocate(totalSizeToAlloc<Expr *>(NumSubExprs),
+ alignof(RecoveryExpr));
+ return new (Mem) RecoveryExpr(EmptyShell(), NumSubExprs);
+}
+
+void OMPArrayShapingExpr::setDimensions(ArrayRef<Expr *> Dims) {
+ assert(
+ NumDims == Dims.size() &&
+ "Preallocated number of dimensions is different from the provided one.");
+ llvm::copy(Dims, getTrailingObjects<Expr *>());
+}
+
+void OMPArrayShapingExpr::setBracketsRanges(ArrayRef<SourceRange> BR) {
+ assert(
+ NumDims == BR.size() &&
+ "Preallocated number of dimensions is different from the provided one.");
+ llvm::copy(BR, getTrailingObjects<SourceRange>());
+}
+
+OMPArrayShapingExpr::OMPArrayShapingExpr(QualType ExprTy, Expr *Op,
+ SourceLocation L, SourceLocation R,
+ ArrayRef<Expr *> Dims)
+ : Expr(OMPArrayShapingExprClass, ExprTy, VK_LValue, OK_Ordinary), LPLoc(L),
+ RPLoc(R), NumDims(Dims.size()) {
+ setBase(Op);
+ setDimensions(Dims);
+ setDependence(computeDependence(this));
+}
+
+OMPArrayShapingExpr *
+OMPArrayShapingExpr::Create(const ASTContext &Context, QualType T, Expr *Op,
+ SourceLocation L, SourceLocation R,
+ ArrayRef<Expr *> Dims,
+ ArrayRef<SourceRange> BracketRanges) {
+ assert(Dims.size() == BracketRanges.size() &&
+ "Different number of dimensions and brackets ranges.");
+ void *Mem = Context.Allocate(
+ totalSizeToAlloc<Expr *, SourceRange>(Dims.size() + 1, Dims.size()),
+ alignof(OMPArrayShapingExpr));
+ auto *E = new (Mem) OMPArrayShapingExpr(T, Op, L, R, Dims);
+ E->setBracketsRanges(BracketRanges);
+ return E;
+}
+
+OMPArrayShapingExpr *OMPArrayShapingExpr::CreateEmpty(const ASTContext &Context,
+ unsigned NumDims) {
+ void *Mem = Context.Allocate(
+ totalSizeToAlloc<Expr *, SourceRange>(NumDims + 1, NumDims),
+ alignof(OMPArrayShapingExpr));
+ return new (Mem) OMPArrayShapingExpr(EmptyShell(), NumDims);
+}
+
+void OMPIteratorExpr::setIteratorDeclaration(unsigned I, Decl *D) {
+ assert(I < NumIterators &&
+ "Idx is greater or equal the number of iterators definitions.");
+ getTrailingObjects<Decl *>()[I] = D;
+}
+
+void OMPIteratorExpr::setAssignmentLoc(unsigned I, SourceLocation Loc) {
+ assert(I < NumIterators &&
+ "Idx is greater or equal the number of iterators definitions.");
+ getTrailingObjects<
+ SourceLocation>()[I * static_cast<int>(RangeLocOffset::Total) +
+ static_cast<int>(RangeLocOffset::AssignLoc)] = Loc;
+}
+
+void OMPIteratorExpr::setIteratorRange(unsigned I, Expr *Begin,
+ SourceLocation ColonLoc, Expr *End,
+ SourceLocation SecondColonLoc,
+ Expr *Step) {
+ assert(I < NumIterators &&
+ "Idx is greater or equal the number of iterators definitions.");
+ getTrailingObjects<Expr *>()[I * static_cast<int>(RangeExprOffset::Total) +
+ static_cast<int>(RangeExprOffset::Begin)] =
+ Begin;
+ getTrailingObjects<Expr *>()[I * static_cast<int>(RangeExprOffset::Total) +
+ static_cast<int>(RangeExprOffset::End)] = End;
+ getTrailingObjects<Expr *>()[I * static_cast<int>(RangeExprOffset::Total) +
+ static_cast<int>(RangeExprOffset::Step)] = Step;
+ getTrailingObjects<
+ SourceLocation>()[I * static_cast<int>(RangeLocOffset::Total) +
+ static_cast<int>(RangeLocOffset::FirstColonLoc)] =
+ ColonLoc;
+ getTrailingObjects<
+ SourceLocation>()[I * static_cast<int>(RangeLocOffset::Total) +
+ static_cast<int>(RangeLocOffset::SecondColonLoc)] =
+ SecondColonLoc;
+}
+
+Decl *OMPIteratorExpr::getIteratorDecl(unsigned I) {
+ return getTrailingObjects<Decl *>()[I];
+}
+
+OMPIteratorExpr::IteratorRange OMPIteratorExpr::getIteratorRange(unsigned I) {
+ IteratorRange Res;
+ Res.Begin =
+ getTrailingObjects<Expr *>()[I * static_cast<int>(
+ RangeExprOffset::Total) +
+ static_cast<int>(RangeExprOffset::Begin)];
+ Res.End =
+ getTrailingObjects<Expr *>()[I * static_cast<int>(
+ RangeExprOffset::Total) +
+ static_cast<int>(RangeExprOffset::End)];
+ Res.Step =
+ getTrailingObjects<Expr *>()[I * static_cast<int>(
+ RangeExprOffset::Total) +
+ static_cast<int>(RangeExprOffset::Step)];
+ return Res;
+}
+
+SourceLocation OMPIteratorExpr::getAssignLoc(unsigned I) const {
+ return getTrailingObjects<
+ SourceLocation>()[I * static_cast<int>(RangeLocOffset::Total) +
+ static_cast<int>(RangeLocOffset::AssignLoc)];
+}
+
+SourceLocation OMPIteratorExpr::getColonLoc(unsigned I) const {
+ return getTrailingObjects<
+ SourceLocation>()[I * static_cast<int>(RangeLocOffset::Total) +
+ static_cast<int>(RangeLocOffset::FirstColonLoc)];
+}
+
+SourceLocation OMPIteratorExpr::getSecondColonLoc(unsigned I) const {
+ return getTrailingObjects<
+ SourceLocation>()[I * static_cast<int>(RangeLocOffset::Total) +
+ static_cast<int>(RangeLocOffset::SecondColonLoc)];
+}
+
+void OMPIteratorExpr::setHelper(unsigned I, const OMPIteratorHelperData &D) {
+ getTrailingObjects<OMPIteratorHelperData>()[I] = D;
+}
+
+OMPIteratorHelperData &OMPIteratorExpr::getHelper(unsigned I) {
+ return getTrailingObjects<OMPIteratorHelperData>()[I];
+}
+
+const OMPIteratorHelperData &OMPIteratorExpr::getHelper(unsigned I) const {
+ return getTrailingObjects<OMPIteratorHelperData>()[I];
+}
+
+OMPIteratorExpr::OMPIteratorExpr(
+ QualType ExprTy, SourceLocation IteratorKwLoc, SourceLocation L,
+ SourceLocation R, ArrayRef<OMPIteratorExpr::IteratorDefinition> Data,
+ ArrayRef<OMPIteratorHelperData> Helpers)
+ : Expr(OMPIteratorExprClass, ExprTy, VK_LValue, OK_Ordinary),
+ IteratorKwLoc(IteratorKwLoc), LPLoc(L), RPLoc(R),
+ NumIterators(Data.size()) {
+ for (unsigned I = 0, E = Data.size(); I < E; ++I) {
+ const IteratorDefinition &D = Data[I];
+ setIteratorDeclaration(I, D.IteratorDecl);
+ setAssignmentLoc(I, D.AssignmentLoc);
+ setIteratorRange(I, D.Range.Begin, D.ColonLoc, D.Range.End,
+ D.SecondColonLoc, D.Range.Step);
+ setHelper(I, Helpers[I]);
+ }
+ setDependence(computeDependence(this));
+}
+
+OMPIteratorExpr *
+OMPIteratorExpr::Create(const ASTContext &Context, QualType T,
+ SourceLocation IteratorKwLoc, SourceLocation L,
+ SourceLocation R,
+ ArrayRef<OMPIteratorExpr::IteratorDefinition> Data,
+ ArrayRef<OMPIteratorHelperData> Helpers) {
+ assert(Data.size() == Helpers.size() &&
+ "Data and helpers must have the same size.");
+ void *Mem = Context.Allocate(
+ totalSizeToAlloc<Decl *, Expr *, SourceLocation, OMPIteratorHelperData>(
+ Data.size(), Data.size() * static_cast<int>(RangeExprOffset::Total),
+ Data.size() * static_cast<int>(RangeLocOffset::Total),
+ Helpers.size()),
+ alignof(OMPIteratorExpr));
+ return new (Mem) OMPIteratorExpr(T, IteratorKwLoc, L, R, Data, Helpers);
+}
+
+OMPIteratorExpr *OMPIteratorExpr::CreateEmpty(const ASTContext &Context,
+ unsigned NumIterators) {
+ void *Mem = Context.Allocate(
+ totalSizeToAlloc<Decl *, Expr *, SourceLocation, OMPIteratorHelperData>(
+ NumIterators, NumIterators * static_cast<int>(RangeExprOffset::Total),
+ NumIterators * static_cast<int>(RangeLocOffset::Total), NumIterators),
+ alignof(OMPIteratorExpr));
+ return new (Mem) OMPIteratorExpr(EmptyShell(), NumIterators);
+}
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index 422227d787b10..5d99f61c579ff 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -13,11 +13,14 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/ComputeDependence.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclAccessPair.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclarationName.h"
+#include "clang/AST/DependenceFlags.h"
#include "clang/AST/Expr.h"
#include "clang/AST/LambdaCapture.h"
#include "clang/AST/NestedNameSpecifier.h"
@@ -172,9 +175,7 @@ CXXNewExpr::CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew,
Expr *Initializer, QualType Ty,
TypeSourceInfo *AllocatedTypeInfo, SourceRange Range,
SourceRange DirectInitRange)
- : Expr(CXXNewExprClass, Ty, VK_RValue, OK_Ordinary, Ty->isDependentType(),
- Ty->isDependentType(), Ty->isInstantiationDependentType(),
- Ty->containsUnexpandedParameterPack()),
+ : Expr(CXXNewExprClass, Ty, VK_RValue, OK_Ordinary),
OperatorNew(OperatorNew), OperatorDelete(OperatorDelete),
AllocatedTypeInfo(AllocatedTypeInfo), Range(Range),
DirectInitRange(DirectInitRange) {
@@ -192,42 +193,13 @@ CXXNewExpr::CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew,
CXXNewExprBits.IsParenTypeId = IsParenTypeId;
CXXNewExprBits.NumPlacementArgs = PlacementArgs.size();
- if (ArraySize) {
- if (Expr *SizeExpr = *ArraySize) {
- if (SizeExpr->isValueDependent())
- ExprBits.ValueDependent = true;
- if (SizeExpr->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- if (SizeExpr->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
- }
-
+ if (ArraySize)
getTrailingObjects<Stmt *>()[arraySizeOffset()] = *ArraySize;
- }
-
- if (Initializer) {
- if (Initializer->isValueDependent())
- ExprBits.ValueDependent = true;
- if (Initializer->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- if (Initializer->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
-
+ if (Initializer)
getTrailingObjects<Stmt *>()[initExprOffset()] = Initializer;
- }
-
- for (unsigned I = 0; I != PlacementArgs.size(); ++I) {
- if (PlacementArgs[I]->isValueDependent())
- ExprBits.ValueDependent = true;
- if (PlacementArgs[I]->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- if (PlacementArgs[I]->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
-
+ for (unsigned I = 0; I != PlacementArgs.size(); ++I)
getTrailingObjects<Stmt *>()[placementNewArgsOffset() + I] =
PlacementArgs[I];
- }
-
if (IsParenTypeId)
getTrailingObjects<SourceRange>()[0] = TypeIdParens;
@@ -243,6 +215,8 @@ CXXNewExpr::CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew,
this->Range.setEnd(TypeIdParens.getEnd());
break;
}
+
+ setDependence(computeDependence(this));
}
CXXNewExpr::CXXNewExpr(EmptyShell Empty, bool IsArray,
@@ -330,40 +304,19 @@ PseudoDestructorTypeStorage::PseudoDestructorTypeStorage(TypeSourceInfo *Info)
Location = Info->getTypeLoc().getLocalSourceRange().getBegin();
}
-CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(const ASTContext &Context,
- Expr *Base, bool isArrow, SourceLocation OperatorLoc,
- NestedNameSpecifierLoc QualifierLoc, TypeSourceInfo *ScopeType,
- SourceLocation ColonColonLoc, SourceLocation TildeLoc,
- PseudoDestructorTypeStorage DestroyedType)
- : Expr(CXXPseudoDestructorExprClass,
- Context.BoundMemberTy,
- VK_RValue, OK_Ordinary,
- /*isTypeDependent=*/(Base->isTypeDependent() ||
- (DestroyedType.getTypeSourceInfo() &&
- DestroyedType.getTypeSourceInfo()->getType()->isDependentType())),
- /*isValueDependent=*/Base->isValueDependent(),
- (Base->isInstantiationDependent() ||
- (QualifierLoc &&
- QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent()) ||
- (ScopeType &&
- ScopeType->getType()->isInstantiationDependentType()) ||
- (DestroyedType.getTypeSourceInfo() &&
- DestroyedType.getTypeSourceInfo()->getType()
- ->isInstantiationDependentType())),
- // ContainsUnexpandedParameterPack
- (Base->containsUnexpandedParameterPack() ||
- (QualifierLoc &&
- QualifierLoc.getNestedNameSpecifier()
- ->containsUnexpandedParameterPack()) ||
- (ScopeType &&
- ScopeType->getType()->containsUnexpandedParameterPack()) ||
- (DestroyedType.getTypeSourceInfo() &&
- DestroyedType.getTypeSourceInfo()->getType()
- ->containsUnexpandedParameterPack()))),
- Base(static_cast<Stmt *>(Base)), IsArrow(isArrow),
- OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc),
- ScopeType(ScopeType), ColonColonLoc(ColonColonLoc), TildeLoc(TildeLoc),
- DestroyedType(DestroyedType) {}
+CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(
+ const ASTContext &Context, Expr *Base, bool isArrow,
+ SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
+ TypeSourceInfo *ScopeType, SourceLocation ColonColonLoc,
+ SourceLocation TildeLoc, PseudoDestructorTypeStorage DestroyedType)
+ : Expr(CXXPseudoDestructorExprClass, Context.BoundMemberTy, VK_RValue,
+ OK_Ordinary),
+ Base(static_cast<Stmt *>(Base)), IsArrow(isArrow),
+ OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc),
+ ScopeType(ScopeType), ColonColonLoc(ColonColonLoc), TildeLoc(TildeLoc),
+ DestroyedType(DestroyedType) {
+ setDependence(computeDependence(this));
+}
QualType CXXPseudoDestructorExpr::getDestroyedType() const {
if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo())
@@ -453,62 +406,31 @@ OverloadExpr::OverloadExpr(StmtClass SC, const ASTContext &Context,
UnresolvedSetIterator End, bool KnownDependent,
bool KnownInstantiationDependent,
bool KnownContainsUnexpandedParameterPack)
- : Expr(
- SC, Context.OverloadTy, VK_LValue, OK_Ordinary, KnownDependent,
- KnownDependent,
- (KnownInstantiationDependent || NameInfo.isInstantiationDependent() ||
- (QualifierLoc &&
- QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())),
- (KnownContainsUnexpandedParameterPack ||
- NameInfo.containsUnexpandedParameterPack() ||
- (QualifierLoc && QualifierLoc.getNestedNameSpecifier()
- ->containsUnexpandedParameterPack()))),
- NameInfo(NameInfo), QualifierLoc(QualifierLoc) {
+ : Expr(SC, Context.OverloadTy, VK_LValue, OK_Ordinary), NameInfo(NameInfo),
+ QualifierLoc(QualifierLoc) {
unsigned NumResults = End - Begin;
OverloadExprBits.NumResults = NumResults;
OverloadExprBits.HasTemplateKWAndArgsInfo =
(TemplateArgs != nullptr ) || TemplateKWLoc.isValid();
if (NumResults) {
- // Determine whether this expression is type-dependent.
- for (UnresolvedSetImpl::const_iterator I = Begin; I != End; ++I) {
- if ((*I)->getDeclContext()->isDependentContext() ||
- isa<UnresolvedUsingValueDecl>(*I)) {
- ExprBits.TypeDependent = true;
- ExprBits.ValueDependent = true;
- ExprBits.InstantiationDependent = true;
- }
- }
-
// Copy the results to the trailing array past UnresolvedLookupExpr
// or UnresolvedMemberExpr.
DeclAccessPair *Results = getTrailingResults();
memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair));
}
- // If we have explicit template arguments, check for dependent
- // template arguments and whether they contain any unexpanded pack
- // expansions.
if (TemplateArgs) {
- bool Dependent = false;
- bool InstantiationDependent = false;
- bool ContainsUnexpandedParameterPack = false;
+ auto Deps = TemplateArgumentDependence::None;
getTrailingASTTemplateKWAndArgsInfo()->initializeFrom(
- TemplateKWLoc, *TemplateArgs, getTrailingTemplateArgumentLoc(),
- Dependent, InstantiationDependent, ContainsUnexpandedParameterPack);
-
- if (Dependent) {
- ExprBits.TypeDependent = true;
- ExprBits.ValueDependent = true;
- }
- if (InstantiationDependent)
- ExprBits.InstantiationDependent = true;
- if (ContainsUnexpandedParameterPack)
- ExprBits.ContainsUnexpandedParameterPack = true;
+ TemplateKWLoc, *TemplateArgs, getTrailingTemplateArgumentLoc(), Deps);
} else if (TemplateKWLoc.isValid()) {
getTrailingASTTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc);
}
+ setDependence(computeDependence(this, KnownDependent,
+ KnownInstantiationDependent,
+ KnownContainsUnexpandedParameterPack));
if (isTypeDependent())
setType(Context.DependentTy);
}
@@ -525,31 +447,19 @@ DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(
QualType Ty, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *Args)
- : Expr(
- DependentScopeDeclRefExprClass, Ty, VK_LValue, OK_Ordinary, true,
- true,
- (NameInfo.isInstantiationDependent() ||
- (QualifierLoc &&
- QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())),
- (NameInfo.containsUnexpandedParameterPack() ||
- (QualifierLoc && QualifierLoc.getNestedNameSpecifier()
- ->containsUnexpandedParameterPack()))),
+ : Expr(DependentScopeDeclRefExprClass, Ty, VK_LValue, OK_Ordinary),
QualifierLoc(QualifierLoc), NameInfo(NameInfo) {
DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo =
(Args != nullptr) || TemplateKWLoc.isValid();
if (Args) {
- bool Dependent = true;
- bool InstantiationDependent = true;
- bool ContainsUnexpandedParameterPack
- = ExprBits.ContainsUnexpandedParameterPack;
+ auto Deps = TemplateArgumentDependence::None;
getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
- TemplateKWLoc, *Args, getTrailingObjects<TemplateArgumentLoc>(),
- Dependent, InstantiationDependent, ContainsUnexpandedParameterPack);
- ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
+ TemplateKWLoc, *Args, getTrailingObjects<TemplateArgumentLoc>(), Deps);
} else if (TemplateKWLoc.isValid()) {
getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
TemplateKWLoc);
}
+ setDependence(computeDependence(this));
}
DependentScopeDeclRefExpr *DependentScopeDeclRefExpr::Create(
@@ -615,27 +525,27 @@ CXXOperatorCallExpr::CXXOperatorCallExpr(OverloadedOperatorKind OpKind,
Expr *Fn, ArrayRef<Expr *> Args,
QualType Ty, ExprValueKind VK,
SourceLocation OperatorLoc,
- FPOptions FPFeatures,
+ FPOptionsOverride FPFeatures,
ADLCallKind UsesADL)
: CallExpr(CXXOperatorCallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK,
OperatorLoc, /*MinNumArgs=*/0, UsesADL) {
CXXOperatorCallExprBits.OperatorKind = OpKind;
- CXXOperatorCallExprBits.FPFeatures = FPFeatures.getInt();
assert(
(CXXOperatorCallExprBits.OperatorKind == static_cast<unsigned>(OpKind)) &&
"OperatorKind overflow!");
- assert((CXXOperatorCallExprBits.FPFeatures == FPFeatures.getInt()) &&
- "FPFeatures overflow!");
Range = getSourceRangeImpl();
+ Overrides = FPFeatures;
}
CXXOperatorCallExpr::CXXOperatorCallExpr(unsigned NumArgs, EmptyShell Empty)
: CallExpr(CXXOperatorCallExprClass, /*NumPreArgs=*/0, NumArgs, Empty) {}
-CXXOperatorCallExpr *CXXOperatorCallExpr::Create(
- const ASTContext &Ctx, OverloadedOperatorKind OpKind, Expr *Fn,
- ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
- SourceLocation OperatorLoc, FPOptions FPFeatures, ADLCallKind UsesADL) {
+CXXOperatorCallExpr *
+CXXOperatorCallExpr::Create(const ASTContext &Ctx,
+ OverloadedOperatorKind OpKind, Expr *Fn,
+ ArrayRef<Expr *> Args, QualType Ty,
+ ExprValueKind VK, SourceLocation OperatorLoc,
+ FPOptionsOverride FPFeatures, ADLCallKind UsesADL) {
// Allocate storage for the trailing objects of CallExpr.
unsigned NumArgs = Args.size();
unsigned SizeOfTrailingObjects =
@@ -667,7 +577,7 @@ SourceRange CXXOperatorCallExpr::getSourceRangeImpl() const {
// Postfix operator
return SourceRange(getArg(0)->getBeginLoc(), getOperatorLoc());
} else if (Kind == OO_Arrow) {
- return getArg(0)->getSourceRange();
+ return SourceRange(getArg(0)->getBeginLoc(), getOperatorLoc());
} else if (Kind == OO_Call) {
return SourceRange(getArg(0)->getBeginLoc(), getRParenLoc());
} else if (Kind == OO_Subscript) {
@@ -766,6 +676,7 @@ const char *CXXNamedCastExpr::getCastName() const {
case CXXDynamicCastExprClass: return "dynamic_cast";
case CXXReinterpretCastExprClass: return "reinterpret_cast";
case CXXConstCastExprClass: return "const_cast";
+ case CXXAddrspaceCastExprClass: return "addrspace_cast";
default: return "<invalid cast>";
}
}
@@ -890,6 +801,19 @@ CXXConstCastExpr *CXXConstCastExpr::CreateEmpty(const ASTContext &C) {
return new (C) CXXConstCastExpr(EmptyShell());
}
+CXXAddrspaceCastExpr *
+CXXAddrspaceCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK,
+ CastKind K, Expr *Op, TypeSourceInfo *WrittenTy,
+ SourceLocation L, SourceLocation RParenLoc,
+ SourceRange AngleBrackets) {
+ return new (C) CXXAddrspaceCastExpr(T, VK, K, Op, WrittenTy, L, RParenLoc,
+ AngleBrackets);
+}
+
+CXXAddrspaceCastExpr *CXXAddrspaceCastExpr::CreateEmpty(const ASTContext &C) {
+ return new (C) CXXAddrspaceCastExpr(EmptyShell());
+}
+
CXXFunctionalCastExpr *
CXXFunctionalCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK,
TypeSourceInfo *Written, CastKind K, Expr *Op,
@@ -989,17 +913,19 @@ const IdentifierInfo *UserDefinedLiteral::getUDSuffix() const {
return cast<FunctionDecl>(getCalleeDecl())->getLiteralIdentifier();
}
-CXXDefaultInitExpr::CXXDefaultInitExpr(const ASTContext &Ctx, SourceLocation Loc,
- FieldDecl *Field, QualType Ty,
- DeclContext *UsedContext)
+CXXDefaultInitExpr::CXXDefaultInitExpr(const ASTContext &Ctx,
+ SourceLocation Loc, FieldDecl *Field,
+ QualType Ty, DeclContext *UsedContext)
: Expr(CXXDefaultInitExprClass, Ty.getNonLValueExprType(Ctx),
- Ty->isLValueReferenceType() ? VK_LValue : Ty->isRValueReferenceType()
- ? VK_XValue
- : VK_RValue,
- /*FIXME*/ OK_Ordinary, false, false, false, false),
+ Ty->isLValueReferenceType()
+ ? VK_LValue
+ : Ty->isRValueReferenceType() ? VK_XValue : VK_RValue,
+ /*FIXME*/ OK_Ordinary),
Field(Field), UsedContext(UsedContext) {
CXXDefaultInitExprBits.Loc = Loc;
assert(Field->hasInClassInitializer());
+
+ setDependence(ExprDependence::None);
}
CXXTemporary *CXXTemporary::Create(const ASTContext &C,
@@ -1097,11 +1023,8 @@ CXXConstructExpr::CXXConstructExpr(
bool ListInitialization, bool StdInitListInitialization,
bool ZeroInitialization, ConstructionKind ConstructKind,
SourceRange ParenOrBraceRange)
- : Expr(SC, Ty, VK_RValue, OK_Ordinary, Ty->isDependentType(),
- Ty->isDependentType(), Ty->isInstantiationDependentType(),
- Ty->containsUnexpandedParameterPack()),
- Constructor(Ctor), ParenOrBraceRange(ParenOrBraceRange),
- NumArgs(Args.size()) {
+ : Expr(SC, Ty, VK_RValue, OK_Ordinary), Constructor(Ctor),
+ ParenOrBraceRange(ParenOrBraceRange), NumArgs(Args.size()) {
CXXConstructExprBits.Elidable = Elidable;
CXXConstructExprBits.HadMultipleCandidates = HadMultipleCandidates;
CXXConstructExprBits.ListInitialization = ListInitialization;
@@ -1113,16 +1036,10 @@ CXXConstructExpr::CXXConstructExpr(
Stmt **TrailingArgs = getTrailingArgs();
for (unsigned I = 0, N = Args.size(); I != N; ++I) {
assert(Args[I] && "NULL argument in CXXConstructExpr!");
-
- if (Args[I]->isValueDependent())
- ExprBits.ValueDependent = true;
- if (Args[I]->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- if (Args[I]->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
-
TrailingArgs[I] = Args[I];
}
+
+ setDependence(computeDependence(this));
}
CXXConstructExpr::CXXConstructExpr(StmtClass SC, EmptyShell Empty,
@@ -1170,37 +1087,22 @@ LambdaCaptureKind LambdaCapture::getCaptureKind() const {
LambdaExpr::LambdaExpr(QualType T, SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
- SourceLocation CaptureDefaultLoc,
- ArrayRef<LambdaCapture> Captures, bool ExplicitParams,
+ SourceLocation CaptureDefaultLoc, bool ExplicitParams,
bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
SourceLocation ClosingBrace,
bool ContainsUnexpandedParameterPack)
- : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary, T->isDependentType(),
- T->isDependentType(), T->isDependentType(),
- ContainsUnexpandedParameterPack),
+ : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary),
IntroducerRange(IntroducerRange), CaptureDefaultLoc(CaptureDefaultLoc),
- NumCaptures(Captures.size()), CaptureDefault(CaptureDefault),
- ExplicitParams(ExplicitParams), ExplicitResultType(ExplicitResultType),
ClosingBrace(ClosingBrace) {
- assert(CaptureInits.size() == Captures.size() && "Wrong number of arguments");
+ LambdaExprBits.NumCaptures = CaptureInits.size();
+ LambdaExprBits.CaptureDefault = CaptureDefault;
+ LambdaExprBits.ExplicitParams = ExplicitParams;
+ LambdaExprBits.ExplicitResultType = ExplicitResultType;
+
CXXRecordDecl *Class = getLambdaClass();
- CXXRecordDecl::LambdaDefinitionData &Data = Class->getLambdaData();
-
- // FIXME: Propagate "has unexpanded parameter pack" bit.
-
- // Copy captures.
- const ASTContext &Context = Class->getASTContext();
- Data.NumCaptures = NumCaptures;
- Data.NumExplicitCaptures = 0;
- Data.Captures =
- (LambdaCapture *)Context.Allocate(sizeof(LambdaCapture) * NumCaptures);
- LambdaCapture *ToCapture = Data.Captures;
- for (unsigned I = 0, N = Captures.size(); I != N; ++I) {
- if (Captures[I].isExplicit())
- ++Data.NumExplicitCaptures;
-
- *ToCapture++ = Captures[I];
- }
+ (void)Class;
+ assert(capture_size() == Class->capture_size() && "Wrong number of captures");
+ assert(getCaptureDefault() == Class->getLambdaCaptureDefault());
// Copy initialization expressions for the non-static data members.
Stmt **Stored = getStoredStmts();
@@ -1209,24 +1111,37 @@ LambdaExpr::LambdaExpr(QualType T, SourceRange IntroducerRange,
// Copy the body of the lambda.
*Stored++ = getCallOperator()->getBody();
+
+ setDependence(computeDependence(this, ContainsUnexpandedParameterPack));
}
-LambdaExpr *LambdaExpr::Create(
- const ASTContext &Context, CXXRecordDecl *Class,
- SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault,
- SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures,
- bool ExplicitParams, bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
- SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack) {
+LambdaExpr::LambdaExpr(EmptyShell Empty, unsigned NumCaptures)
+ : Expr(LambdaExprClass, Empty) {
+ LambdaExprBits.NumCaptures = NumCaptures;
+
+ // Initially don't initialize the body of the LambdaExpr. The body will
+ // be lazily deserialized when needed.
+ getStoredStmts()[NumCaptures] = nullptr; // Not one past the end.
+}
+
+LambdaExpr *LambdaExpr::Create(const ASTContext &Context, CXXRecordDecl *Class,
+ SourceRange IntroducerRange,
+ LambdaCaptureDefault CaptureDefault,
+ SourceLocation CaptureDefaultLoc,
+ bool ExplicitParams, bool ExplicitResultType,
+ ArrayRef<Expr *> CaptureInits,
+ SourceLocation ClosingBrace,
+ bool ContainsUnexpandedParameterPack) {
// Determine the type of the expression (i.e., the type of the
// function object we're creating).
QualType T = Context.getTypeDeclType(Class);
- unsigned Size = totalSizeToAlloc<Stmt *>(Captures.size() + 1);
+ unsigned Size = totalSizeToAlloc<Stmt *>(CaptureInits.size() + 1);
void *Mem = Context.Allocate(Size);
return new (Mem)
LambdaExpr(T, IntroducerRange, CaptureDefault, CaptureDefaultLoc,
- Captures, ExplicitParams, ExplicitResultType, CaptureInits,
- ClosingBrace, ContainsUnexpandedParameterPack);
+ ExplicitParams, ExplicitResultType, CaptureInits, ClosingBrace,
+ ContainsUnexpandedParameterPack);
}
LambdaExpr *LambdaExpr::CreateDeserialized(const ASTContext &C,
@@ -1236,6 +1151,25 @@ LambdaExpr *LambdaExpr::CreateDeserialized(const ASTContext &C,
return new (Mem) LambdaExpr(EmptyShell(), NumCaptures);
}
+void LambdaExpr::initBodyIfNeeded() const {
+ if (!getStoredStmts()[capture_size()]) {
+ auto *This = const_cast<LambdaExpr *>(this);
+ This->getStoredStmts()[capture_size()] = getCallOperator()->getBody();
+ }
+}
+
+Stmt *LambdaExpr::getBody() const {
+ initBodyIfNeeded();
+ return getStoredStmts()[capture_size()];
+}
+
+const CompoundStmt *LambdaExpr::getCompoundStmtBody() const {
+ Stmt *Body = getBody();
+ if (const auto *CoroBody = dyn_cast<CoroutineBodyStmt>(Body))
+ return cast<CompoundStmt>(CoroBody->getBody());
+ return cast<CompoundStmt>(Body);
+}
+
bool LambdaExpr::isInitCapture(const LambdaCapture *C) const {
return (C->capturesVariable() && C->getCapturedVar()->isInitCapture() &&
(getCallOperator() == C->getCapturedVar()->getDeclContext()));
@@ -1246,7 +1180,7 @@ LambdaExpr::capture_iterator LambdaExpr::capture_begin() const {
}
LambdaExpr::capture_iterator LambdaExpr::capture_end() const {
- return capture_begin() + NumCaptures;
+ return capture_begin() + capture_size();
}
LambdaExpr::capture_range LambdaExpr::captures() const {
@@ -1303,19 +1237,17 @@ ArrayRef<NamedDecl *> LambdaExpr::getExplicitTemplateParameters() const {
return Record->getLambdaExplicitTemplateParameters();
}
-CompoundStmt *LambdaExpr::getBody() const {
- // FIXME: this mutation in getBody is bogus. It should be
- // initialized in ASTStmtReader::VisitLambdaExpr, but for reasons I
- // don't understand, that doesn't work.
- if (!getStoredStmts()[NumCaptures])
- *const_cast<Stmt **>(&getStoredStmts()[NumCaptures]) =
- getCallOperator()->getBody();
+bool LambdaExpr::isMutable() const { return !getCallOperator()->isConst(); }
- return static_cast<CompoundStmt *>(getStoredStmts()[NumCaptures]);
+LambdaExpr::child_range LambdaExpr::children() {
+ initBodyIfNeeded();
+ return child_range(getStoredStmts(), getStoredStmts() + capture_size() + 1);
}
-bool LambdaExpr::isMutable() const {
- return !getCallOperator()->isConst();
+LambdaExpr::const_child_range LambdaExpr::children() const {
+ initBodyIfNeeded();
+ return const_child_range(getStoredStmts(),
+ getStoredStmts() + capture_size() + 1);
}
ExprWithCleanups::ExprWithCleanups(Expr *subexpr,
@@ -1360,19 +1292,13 @@ CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *TSI,
? VK_LValue
: TSI->getType()->isRValueReferenceType() ? VK_XValue
: VK_RValue),
- OK_Ordinary,
- TSI->getType()->isDependentType() ||
- TSI->getType()->getContainedDeducedType(),
- true, true, TSI->getType()->containsUnexpandedParameterPack()),
+ OK_Ordinary),
TSI(TSI), LParenLoc(LParenLoc), RParenLoc(RParenLoc) {
CXXUnresolvedConstructExprBits.NumArgs = Args.size();
auto **StoredArgs = getTrailingObjects<Expr *>();
- for (unsigned I = 0; I != Args.size(); ++I) {
- if (Args[I]->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
-
+ for (unsigned I = 0; I != Args.size(); ++I)
StoredArgs[I] = Args[I];
- }
+ setDependence(computeDependence(this));
}
CXXUnresolvedConstructExpr *CXXUnresolvedConstructExpr::Create(
@@ -1400,11 +1326,7 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs)
: Expr(CXXDependentScopeMemberExprClass, Ctx.DependentTy, VK_LValue,
- OK_Ordinary, true, true, true,
- ((Base && Base->containsUnexpandedParameterPack()) ||
- (QualifierLoc && QualifierLoc.getNestedNameSpecifier()
- ->containsUnexpandedParameterPack()) ||
- MemberNameInfo.containsUnexpandedParameterPack())),
+ OK_Ordinary),
Base(Base), BaseType(BaseType), QualifierLoc(QualifierLoc),
MemberNameInfo(MemberNameInfo) {
CXXDependentScopeMemberExprBits.IsArrow = IsArrow;
@@ -1415,14 +1337,10 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
CXXDependentScopeMemberExprBits.OperatorLoc = OperatorLoc;
if (TemplateArgs) {
- bool Dependent = true;
- bool InstantiationDependent = true;
- bool ContainsUnexpandedParameterPack = false;
+ auto Deps = TemplateArgumentDependence::None;
getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
TemplateKWLoc, *TemplateArgs, getTrailingObjects<TemplateArgumentLoc>(),
- Dependent, InstantiationDependent, ContainsUnexpandedParameterPack);
- if (ContainsUnexpandedParameterPack)
- ExprBits.ContainsUnexpandedParameterPack = true;
+ Deps);
} else if (TemplateKWLoc.isValid()) {
getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
TemplateKWLoc);
@@ -1430,6 +1348,7 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
if (hasFirstQualifierFoundInScope())
*getTrailingObjects<NamedDecl *>() = FirstQualifierFoundInScope;
+ setDependence(computeDependence(this));
}
CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
@@ -1611,16 +1530,15 @@ SizeOfPackExpr *SizeOfPackExpr::CreateDeserialized(ASTContext &Context,
return new (Storage) SizeOfPackExpr(EmptyShell(), NumPartialArgs);
}
-SubstNonTypeTemplateParmPackExpr::
-SubstNonTypeTemplateParmPackExpr(QualType T,
- ExprValueKind ValueKind,
- NonTypeTemplateParmDecl *Param,
- SourceLocation NameLoc,
- const TemplateArgument &ArgPack)
- : Expr(SubstNonTypeTemplateParmPackExprClass, T, ValueKind, OK_Ordinary,
- true, true, true, true),
+SubstNonTypeTemplateParmPackExpr::SubstNonTypeTemplateParmPackExpr(
+ QualType T, ExprValueKind ValueKind, NonTypeTemplateParmDecl *Param,
+ SourceLocation NameLoc, const TemplateArgument &ArgPack)
+ : Expr(SubstNonTypeTemplateParmPackExprClass, T, ValueKind, OK_Ordinary),
Param(Param), Arguments(ArgPack.pack_begin()),
- NumArguments(ArgPack.pack_size()), NameLoc(NameLoc) {}
+ NumArguments(ArgPack.pack_size()), NameLoc(NameLoc) {
+ setDependence(ExprDependence::TypeValueInstantiation |
+ ExprDependence::UnexpandedPack);
+}
TemplateArgument SubstNonTypeTemplateParmPackExpr::getArgumentPack() const {
return TemplateArgument(llvm::makeArrayRef(Arguments, NumArguments));
@@ -1630,12 +1548,13 @@ FunctionParmPackExpr::FunctionParmPackExpr(QualType T, VarDecl *ParamPack,
SourceLocation NameLoc,
unsigned NumParams,
VarDecl *const *Params)
- : Expr(FunctionParmPackExprClass, T, VK_LValue, OK_Ordinary, true, true,
- true, true),
+ : Expr(FunctionParmPackExprClass, T, VK_LValue, OK_Ordinary),
ParamPack(ParamPack), NameLoc(NameLoc), NumParameters(NumParams) {
if (Params)
std::uninitialized_copy(Params, Params + NumParams,
getTrailingObjects<VarDecl *>());
+ setDependence(ExprDependence::TypeValueInstantiation |
+ ExprDependence::UnexpandedPack);
}
FunctionParmPackExpr *
@@ -1657,16 +1576,14 @@ MaterializeTemporaryExpr::MaterializeTemporaryExpr(
QualType T, Expr *Temporary, bool BoundToLvalueReference,
LifetimeExtendedTemporaryDecl *MTD)
: Expr(MaterializeTemporaryExprClass, T,
- BoundToLvalueReference ? VK_LValue : VK_XValue, OK_Ordinary,
- Temporary->isTypeDependent(), Temporary->isValueDependent(),
- Temporary->isInstantiationDependent(),
- Temporary->containsUnexpandedParameterPack()) {
+ BoundToLvalueReference ? VK_LValue : VK_XValue, OK_Ordinary) {
if (MTD) {
State = MTD;
MTD->ExprWithTemporary = Temporary;
return;
}
State = Temporary;
+ setDependence(computeDependence(this));
}
void MaterializeTemporaryExpr::setExtendingDecl(ValueDecl *ExtendedBy,
@@ -1688,30 +1605,23 @@ void MaterializeTemporaryExpr::setExtendingDecl(ValueDecl *ExtendedBy,
TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
ArrayRef<TypeSourceInfo *> Args,
- SourceLocation RParenLoc,
- bool Value)
- : Expr(TypeTraitExprClass, T, VK_RValue, OK_Ordinary,
- /*TypeDependent=*/false,
- /*ValueDependent=*/false,
- /*InstantiationDependent=*/false,
- /*ContainsUnexpandedParameterPack=*/false),
- Loc(Loc), RParenLoc(RParenLoc) {
+ SourceLocation RParenLoc, bool Value)
+ : Expr(TypeTraitExprClass, T, VK_RValue, OK_Ordinary), Loc(Loc),
+ RParenLoc(RParenLoc) {
+ assert(Kind <= TT_Last && "invalid enum value!");
TypeTraitExprBits.Kind = Kind;
+ assert(static_cast<unsigned>(Kind) == TypeTraitExprBits.Kind &&
+ "TypeTraitExprBits.Kind overflow!");
TypeTraitExprBits.Value = Value;
TypeTraitExprBits.NumArgs = Args.size();
+ assert(Args.size() == TypeTraitExprBits.NumArgs &&
+ "TypeTraitExprBits.NumArgs overflow!");
auto **ToArgs = getTrailingObjects<TypeSourceInfo *>();
-
- for (unsigned I = 0, N = Args.size(); I != N; ++I) {
- if (Args[I]->getType()->isDependentType())
- setValueDependent(true);
- if (Args[I]->getType()->isInstantiationDependentType())
- setInstantiationDependent(true);
- if (Args[I]->getType()->containsUnexpandedParameterPack())
- setContainsUnexpandedParameterPack(true);
-
+ for (unsigned I = 0, N = Args.size(); I != N; ++I)
ToArgs[I] = Args[I];
- }
+
+ setDependence(computeDependence(this));
}
TypeTraitExpr *TypeTraitExpr::Create(const ASTContext &C, QualType T,
@@ -1764,81 +1674,3 @@ CUDAKernelCallExpr *CUDAKernelCallExpr::CreateEmpty(const ASTContext &Ctx,
alignof(CUDAKernelCallExpr));
return new (Mem) CUDAKernelCallExpr(NumArgs, Empty);
}
-
-ConceptSpecializationExpr::ConceptSpecializationExpr(const ASTContext &C,
- NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
- DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl,
- ConceptDecl *NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten,
- ArrayRef<TemplateArgument> ConvertedArgs,
- const ConstraintSatisfaction *Satisfaction)
- : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary,
- /*TypeDependent=*/false,
- // All the flags below are set in setTemplateArguments.
- /*ValueDependent=*/!Satisfaction, /*InstantiationDependent=*/false,
- /*ContainsUnexpandedParameterPacks=*/false),
- ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl,
- NamedConcept, ArgsAsWritten),
- NumTemplateArgs(ConvertedArgs.size()),
- Satisfaction(Satisfaction ?
- ASTConstraintSatisfaction::Create(C, *Satisfaction) :
- nullptr) {
- setTemplateArguments(ConvertedArgs);
-}
-
-ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty,
- unsigned NumTemplateArgs)
- : Expr(ConceptSpecializationExprClass, Empty), ConceptReference(),
- NumTemplateArgs(NumTemplateArgs) { }
-
-void ConceptSpecializationExpr::setTemplateArguments(
- ArrayRef<TemplateArgument> Converted) {
- assert(Converted.size() == NumTemplateArgs);
- std::uninitialized_copy(Converted.begin(), Converted.end(),
- getTrailingObjects<TemplateArgument>());
- bool IsInstantiationDependent = false;
- bool ContainsUnexpandedParameterPack = false;
- for (const TemplateArgument& Arg : Converted) {
- if (Arg.isInstantiationDependent())
- IsInstantiationDependent = true;
- if (Arg.containsUnexpandedParameterPack())
- ContainsUnexpandedParameterPack = true;
- if (ContainsUnexpandedParameterPack && IsInstantiationDependent)
- break;
- }
-
- // Currently guaranteed by the fact concepts can only be at namespace-scope.
- assert(!NestedNameSpec ||
- (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() &&
- !NestedNameSpec.getNestedNameSpecifier()
- ->containsUnexpandedParameterPack()));
- setInstantiationDependent(IsInstantiationDependent);
- setContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack);
- assert((!isValueDependent() || isInstantiationDependent()) &&
- "should not be value-dependent");
-}
-
-ConceptSpecializationExpr *
-ConceptSpecializationExpr::Create(const ASTContext &C,
- NestedNameSpecifierLoc NNS,
- SourceLocation TemplateKWLoc,
- DeclarationNameInfo ConceptNameInfo,
- NamedDecl *FoundDecl,
- ConceptDecl *NamedConcept,
- const ASTTemplateArgumentListInfo *ArgsAsWritten,
- ArrayRef<TemplateArgument> ConvertedArgs,
- const ConstraintSatisfaction *Satisfaction) {
- void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
- ConvertedArgs.size()));
- return new (Buffer) ConceptSpecializationExpr(C, NNS, TemplateKWLoc,
- ConceptNameInfo, FoundDecl,
- NamedConcept, ArgsAsWritten,
- ConvertedArgs, Satisfaction);
-}
-
-ConceptSpecializationExpr *
-ConceptSpecializationExpr::Create(ASTContext &C, EmptyShell Empty,
- unsigned NumTemplateArgs) {
- void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
- NumTemplateArgs));
- return new (Buffer) ConceptSpecializationExpr(Empty, NumTemplateArgs);
-}
diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp
index 9dbf6fe9e0f06..31aa734ffedba 100644
--- a/clang/lib/AST/ExprClassification.cpp
+++ b/clang/lib/AST/ExprClassification.cpp
@@ -124,6 +124,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::ObjCPropertyRefExprClass:
// C++ [expr.typeid]p1: The result of a typeid expression is an lvalue of...
case Expr::CXXTypeidExprClass:
+ case Expr::CXXUuidofExprClass:
// Unresolved lookups and uncorrected typos get classified as lvalues.
// FIXME: Is this wise? Should they get their own kind?
case Expr::UnresolvedLookupExprClass:
@@ -139,6 +140,8 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::MSPropertyRefExprClass:
case Expr::MSPropertySubscriptExprClass:
case Expr::OMPArraySectionExprClass:
+ case Expr::OMPArrayShapingExprClass:
+ case Expr::OMPIteratorExprClass:
return Cl::CL_LValue;
// C99 6.5.2.5p5 says that compound literals are lvalues.
@@ -193,6 +196,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::DesignatedInitUpdateExprClass:
case Expr::SourceLocExprClass:
case Expr::ConceptSpecializationExprClass:
+ case Expr::RequiresExprClass:
return Cl::CL_PRValue;
case Expr::ConstantExprClass:
@@ -219,6 +223,10 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
}
return Cl::CL_LValue;
+ // Subscripting matrix types behaves like member accesses.
+ case Expr::MatrixSubscriptExprClass:
+ return ClassifyInternal(Ctx, cast<MatrixSubscriptExpr>(E)->getBase());
+
// C++ [expr.prim.general]p3: The result is an lvalue if the entity is a
// function or variable and a prvalue otherwise.
case Expr::DeclRefExprClass:
@@ -267,6 +275,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
return Cl::CL_PRValue;
}
+ case Expr::RecoveryExprClass:
case Expr::OpaqueValueExprClass:
return ClassifyExprValueKind(Lang, E, E->getValueKind());
@@ -347,6 +356,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::CXXDynamicCastExprClass:
case Expr::CXXReinterpretCastExprClass:
case Expr::CXXConstCastExprClass:
+ case Expr::CXXAddrspaceCastExprClass:
case Expr::ObjCBridgedCastExprClass:
case Expr::BuiltinBitCastExprClass:
// Only in C++ can casts be interesting at all.
@@ -401,9 +411,6 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
return Cl::CL_PRValue;
}
- case Expr::CXXUuidofExprClass:
- return Cl::CL_LValue;
-
case Expr::PackExpansionExprClass:
return ClassifyInternal(Ctx, cast<PackExpansionExpr>(E)->getPattern());
@@ -451,6 +458,7 @@ static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) {
islvalue = isa<VarDecl>(D) || isa<FieldDecl>(D) ||
isa<IndirectFieldDecl>(D) ||
isa<BindingDecl>(D) ||
+ isa<MSGuidDecl>(D) ||
(Ctx.getLangOpts().CPlusPlus &&
(isa<FunctionDecl>(D) || isa<MSPropertyDecl>(D) ||
isa<FunctionTemplateDecl>(D)));
diff --git a/clang/lib/AST/ExprConcepts.cpp b/clang/lib/AST/ExprConcepts.cpp
new file mode 100644
index 0000000000000..d00d8329095c0
--- /dev/null
+++ b/clang/lib/AST/ExprConcepts.cpp
@@ -0,0 +1,215 @@
+//===- ExprCXX.cpp - (C++) Expression AST Node Implementation -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the subclesses of Expr class declared in ExprCXX.h
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ExprConcepts.h"
+#include "clang/AST/ASTConcept.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ComputeDependence.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/DependenceFlags.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/Support/TrailingObjects.h"
+#include <algorithm>
+#include <string>
+#include <utility>
+
+using namespace clang;
+
+ConceptSpecializationExpr::ConceptSpecializationExpr(
+ const ASTContext &C, NestedNameSpecifierLoc NNS,
+ SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
+ NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
+ const ASTTemplateArgumentListInfo *ArgsAsWritten,
+ ArrayRef<TemplateArgument> ConvertedArgs,
+ const ConstraintSatisfaction *Satisfaction)
+ : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary),
+ ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl,
+ NamedConcept, ArgsAsWritten),
+ NumTemplateArgs(ConvertedArgs.size()),
+ Satisfaction(Satisfaction
+ ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
+ : nullptr) {
+ setTemplateArguments(ConvertedArgs);
+ setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction));
+
+ // Currently guaranteed by the fact concepts can only be at namespace-scope.
+ assert(!NestedNameSpec ||
+ (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() &&
+ !NestedNameSpec.getNestedNameSpecifier()
+ ->containsUnexpandedParameterPack()));
+ assert((!isValueDependent() || isInstantiationDependent()) &&
+ "should not be value-dependent");
+}
+
+ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty,
+ unsigned NumTemplateArgs)
+ : Expr(ConceptSpecializationExprClass, Empty), ConceptReference(),
+ NumTemplateArgs(NumTemplateArgs) { }
+
+void ConceptSpecializationExpr::setTemplateArguments(
+ ArrayRef<TemplateArgument> Converted) {
+ assert(Converted.size() == NumTemplateArgs);
+ std::uninitialized_copy(Converted.begin(), Converted.end(),
+ getTrailingObjects<TemplateArgument>());
+}
+
+ConceptSpecializationExpr *
+ConceptSpecializationExpr::Create(const ASTContext &C,
+ NestedNameSpecifierLoc NNS,
+ SourceLocation TemplateKWLoc,
+ DeclarationNameInfo ConceptNameInfo,
+ NamedDecl *FoundDecl,
+ ConceptDecl *NamedConcept,
+ const ASTTemplateArgumentListInfo *ArgsAsWritten,
+ ArrayRef<TemplateArgument> ConvertedArgs,
+ const ConstraintSatisfaction *Satisfaction) {
+ void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
+ ConvertedArgs.size()));
+ return new (Buffer) ConceptSpecializationExpr(C, NNS, TemplateKWLoc,
+ ConceptNameInfo, FoundDecl,
+ NamedConcept, ArgsAsWritten,
+ ConvertedArgs, Satisfaction);
+}
+
+ConceptSpecializationExpr::ConceptSpecializationExpr(
+ const ASTContext &C, ConceptDecl *NamedConcept,
+ ArrayRef<TemplateArgument> ConvertedArgs,
+ const ConstraintSatisfaction *Satisfaction, bool Dependent,
+ bool ContainsUnexpandedParameterPack)
+ : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary),
+ ConceptReference(NestedNameSpecifierLoc(), SourceLocation(),
+ DeclarationNameInfo(), NamedConcept, NamedConcept,
+ nullptr),
+ NumTemplateArgs(ConvertedArgs.size()),
+ Satisfaction(Satisfaction
+ ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
+ : nullptr) {
+ setTemplateArguments(ConvertedArgs);
+ ExprDependence D = ExprDependence::None;
+ if (!Satisfaction)
+ D |= ExprDependence::Value;
+ if (Dependent)
+ D |= ExprDependence::Instantiation;
+ if (ContainsUnexpandedParameterPack)
+ D |= ExprDependence::UnexpandedPack;
+ setDependence(D);
+}
+
+ConceptSpecializationExpr *
+ConceptSpecializationExpr::Create(const ASTContext &C,
+ ConceptDecl *NamedConcept,
+ ArrayRef<TemplateArgument> ConvertedArgs,
+ const ConstraintSatisfaction *Satisfaction,
+ bool Dependent,
+ bool ContainsUnexpandedParameterPack) {
+ void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
+ ConvertedArgs.size()));
+ return new (Buffer) ConceptSpecializationExpr(
+ C, NamedConcept, ConvertedArgs, Satisfaction, Dependent,
+ ContainsUnexpandedParameterPack);
+}
+
+ConceptSpecializationExpr *
+ConceptSpecializationExpr::Create(ASTContext &C, EmptyShell Empty,
+ unsigned NumTemplateArgs) {
+ void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
+ NumTemplateArgs));
+ return new (Buffer) ConceptSpecializationExpr(Empty, NumTemplateArgs);
+}
+
+const TypeConstraint *
+concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const {
+ assert(isTypeConstraint());
+ auto TPL =
+ TypeConstraintInfo.getPointer().get<TemplateParameterList *>();
+ return cast<TemplateTypeParmDecl>(TPL->getParam(0))
+ ->getTypeConstraint();
+}
+
+RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc,
+ RequiresExprBodyDecl *Body,
+ ArrayRef<ParmVarDecl *> LocalParameters,
+ ArrayRef<concepts::Requirement *> Requirements,
+ SourceLocation RBraceLoc)
+ : Expr(RequiresExprClass, C.BoolTy, VK_RValue, OK_Ordinary),
+ NumLocalParameters(LocalParameters.size()),
+ NumRequirements(Requirements.size()), Body(Body), RBraceLoc(RBraceLoc) {
+ RequiresExprBits.IsSatisfied = false;
+ RequiresExprBits.RequiresKWLoc = RequiresKWLoc;
+ bool Dependent = false;
+ bool ContainsUnexpandedParameterPack = false;
+ for (ParmVarDecl *P : LocalParameters) {
+ Dependent |= P->getType()->isInstantiationDependentType();
+ ContainsUnexpandedParameterPack |=
+ P->getType()->containsUnexpandedParameterPack();
+ }
+ RequiresExprBits.IsSatisfied = true;
+ for (concepts::Requirement *R : Requirements) {
+ Dependent |= R->isDependent();
+ ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack();
+ if (!Dependent) {
+ RequiresExprBits.IsSatisfied = R->isSatisfied();
+ if (!RequiresExprBits.IsSatisfied)
+ break;
+ }
+ }
+ std::copy(LocalParameters.begin(), LocalParameters.end(),
+ getTrailingObjects<ParmVarDecl *>());
+ std::copy(Requirements.begin(), Requirements.end(),
+ getTrailingObjects<concepts::Requirement *>());
+ RequiresExprBits.IsSatisfied |= Dependent;
+ // FIXME: move the computing dependency logic to ComputeDependence.h
+ if (ContainsUnexpandedParameterPack)
+ setDependence(getDependence() | ExprDependence::UnexpandedPack);
+ // FIXME: this is incorrect for cases where we have a non-dependent
+ // requirement, but its parameters are instantiation-dependent. RequiresExpr
+ // should be instantiation-dependent if it has instantiation-dependent
+ // parameters.
+ if (Dependent)
+ setDependence(getDependence() | ExprDependence::ValueInstantiation);
+}
+
+RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty,
+ unsigned NumLocalParameters,
+ unsigned NumRequirements)
+ : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters),
+ NumRequirements(NumRequirements) { }
+
+RequiresExpr *
+RequiresExpr::Create(ASTContext &C, SourceLocation RequiresKWLoc,
+ RequiresExprBodyDecl *Body,
+ ArrayRef<ParmVarDecl *> LocalParameters,
+ ArrayRef<concepts::Requirement *> Requirements,
+ SourceLocation RBraceLoc) {
+ void *Mem =
+ C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
+ LocalParameters.size(), Requirements.size()),
+ alignof(RequiresExpr));
+ return new (Mem) RequiresExpr(C, RequiresKWLoc, Body, LocalParameters,
+ Requirements, RBraceLoc);
+}
+
+RequiresExpr *
+RequiresExpr::Create(ASTContext &C, EmptyShell Empty,
+ unsigned NumLocalParameters, unsigned NumRequirements) {
+ void *Mem =
+ C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
+ NumLocalParameters, NumRequirements),
+ alignof(RequiresExpr));
+ return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements);
+}
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index c4b27b5d1daa2..d20c2382b6ac1 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -54,6 +54,7 @@
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallBitVector.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"
#include <cstring>
@@ -674,6 +675,7 @@ namespace {
None,
Bases,
AfterBases,
+ AfterFields,
Destroying,
DestroyingBases
};
@@ -821,6 +823,9 @@ namespace {
void finishedConstructingBases() {
EI.ObjectsUnderConstruction[Object] = ConstructionPhase::AfterBases;
}
+ void finishedConstructingFields() {
+ EI.ObjectsUnderConstruction[Object] = ConstructionPhase::AfterFields;
+ }
~EvaluatingConstructorRAII() {
if (DidInsert) EI.ObjectsUnderConstruction.erase(Object);
}
@@ -1417,6 +1422,31 @@ static bool isFormalAccess(AccessKinds AK) {
return isAnyAccess(AK) && AK != AK_Construct && AK != AK_Destroy;
}
+/// Is this kind of axcess valid on an indeterminate object value?
+static bool isValidIndeterminateAccess(AccessKinds AK) {
+ switch (AK) {
+ case AK_Read:
+ case AK_Increment:
+ case AK_Decrement:
+ // These need the object's value.
+ return false;
+
+ case AK_ReadObjectRepresentation:
+ case AK_Assign:
+ case AK_Construct:
+ case AK_Destroy:
+ // Construction and destruction don't need the value.
+ return true;
+
+ case AK_MemberCall:
+ case AK_DynamicCast:
+ case AK_TypeId:
+ // These aren't really meaningful on scalars.
+ return true;
+ }
+ llvm_unreachable("unknown access kind");
+}
+
namespace {
struct ComplexValue {
private:
@@ -1865,7 +1895,8 @@ static bool IsGlobalLValue(APValue::LValueBase B) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D))
return VD->hasGlobalStorage();
// ... the address of a function,
- return isa<FunctionDecl>(D);
+ // ... the address of a GUID [MS extension],
+ return isa<FunctionDecl>(D) || isa<MSGuidDecl>(D);
}
if (B.is<TypeInfoLValue>() || B.is<DynamicAllocLValue>())
@@ -1888,7 +1919,6 @@ static bool IsGlobalLValue(APValue::LValueBase B) {
case Expr::PredefinedExprClass:
case Expr::ObjCStringLiteralClass:
case Expr::ObjCEncodeExprClass:
- case Expr::CXXUuidofExprClass:
return true;
case Expr::ObjCBoxedExprClass:
return cast<ObjCBoxedExpr>(E)->isExpressibleAsConstantInitializer();
@@ -2005,6 +2035,17 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
APValue::LValueBase Base = LVal.getLValueBase();
const SubobjectDesignator &Designator = LVal.getLValueDesignator();
+ if (auto *VD = LVal.getLValueBase().dyn_cast<const ValueDecl *>()) {
+ if (auto *FD = dyn_cast<FunctionDecl>(VD)) {
+ if (FD->isConsteval()) {
+ Info.FFDiag(Loc, diag::note_consteval_address_accessible)
+ << !Type->isAnyPointerType();
+ Info.Note(FD->getLocation(), diag::note_declared_at);
+ return false;
+ }
+ }
+ }
+
// Check that the object is a global. Note that the fake 'this' object we
// manufacture when checking potential constant expressions is conservatively
// assumed to be global here.
@@ -2114,6 +2155,11 @@ static bool CheckMemberPointerConstantExpression(EvalInfo &Info,
const auto *FD = dyn_cast_or_null<CXXMethodDecl>(Member);
if (!FD)
return true;
+ if (FD->isConsteval()) {
+ Info.FFDiag(Loc, diag::note_consteval_address_accessible) << /*pointer*/ 0;
+ Info.Note(FD->getLocation(), diag::note_declared_at);
+ return false;
+ }
return Usage == Expr::EvaluateForMangling || FD->isVirtual() ||
!FD->hasAttr<DLLImportAttr>();
}
@@ -2533,7 +2579,7 @@ static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS,
if (SA != RHS) {
Info.CCEDiag(E, diag::note_constexpr_large_shift)
<< RHS << E->getType() << LHS.getBitWidth();
- } else if (LHS.isSigned() && !Info.getLangOpts().CPlusPlus2a) {
+ } else if (LHS.isSigned() && !Info.getLangOpts().CPlusPlus20) {
// C++11 [expr.shift]p2: A signed left shift must have a non-negative
// operand, and must not overflow the corresponding unsigned type.
// C++2a [expr.shift]p2: E1 << E2 is the unique value congruent to
@@ -2618,6 +2664,155 @@ static bool handleFloatFloatBinOp(EvalInfo &Info, const Expr *E,
return true;
}
+static bool handleLogicalOpForVector(const APInt &LHSValue,
+ BinaryOperatorKind Opcode,
+ const APInt &RHSValue, APInt &Result) {
+ bool LHS = (LHSValue != 0);
+ bool RHS = (RHSValue != 0);
+
+ if (Opcode == BO_LAnd)
+ Result = LHS && RHS;
+ else
+ Result = LHS || RHS;
+ return true;
+}
+static bool handleLogicalOpForVector(const APFloat &LHSValue,
+ BinaryOperatorKind Opcode,
+ const APFloat &RHSValue, APInt &Result) {
+ bool LHS = !LHSValue.isZero();
+ bool RHS = !RHSValue.isZero();
+
+ if (Opcode == BO_LAnd)
+ Result = LHS && RHS;
+ else
+ Result = LHS || RHS;
+ return true;
+}
+
+static bool handleLogicalOpForVector(const APValue &LHSValue,
+ BinaryOperatorKind Opcode,
+ const APValue &RHSValue, APInt &Result) {
+ // The result is always an int type, however operands match the first.
+ if (LHSValue.getKind() == APValue::Int)
+ return handleLogicalOpForVector(LHSValue.getInt(), Opcode,
+ RHSValue.getInt(), Result);
+ assert(LHSValue.getKind() == APValue::Float && "Should be no other options");
+ return handleLogicalOpForVector(LHSValue.getFloat(), Opcode,
+ RHSValue.getFloat(), Result);
+}
+
+template <typename APTy>
+static bool
+handleCompareOpForVectorHelper(const APTy &LHSValue, BinaryOperatorKind Opcode,
+ const APTy &RHSValue, APInt &Result) {
+ switch (Opcode) {
+ default:
+ llvm_unreachable("unsupported binary operator");
+ case BO_EQ:
+ Result = (LHSValue == RHSValue);
+ break;
+ case BO_NE:
+ Result = (LHSValue != RHSValue);
+ break;
+ case BO_LT:
+ Result = (LHSValue < RHSValue);
+ break;
+ case BO_GT:
+ Result = (LHSValue > RHSValue);
+ break;
+ case BO_LE:
+ Result = (LHSValue <= RHSValue);
+ break;
+ case BO_GE:
+ Result = (LHSValue >= RHSValue);
+ break;
+ }
+
+ return true;
+}
+
+static bool handleCompareOpForVector(const APValue &LHSValue,
+ BinaryOperatorKind Opcode,
+ const APValue &RHSValue, APInt &Result) {
+ // The result is always an int type, however operands match the first.
+ if (LHSValue.getKind() == APValue::Int)
+ return handleCompareOpForVectorHelper(LHSValue.getInt(), Opcode,
+ RHSValue.getInt(), Result);
+ assert(LHSValue.getKind() == APValue::Float && "Should be no other options");
+ return handleCompareOpForVectorHelper(LHSValue.getFloat(), Opcode,
+ RHSValue.getFloat(), Result);
+}
+
+// Perform binary operations for vector types, in place on the LHS.
+static bool handleVectorVectorBinOp(EvalInfo &Info, const Expr *E,
+ BinaryOperatorKind Opcode,
+ APValue &LHSValue,
+ const APValue &RHSValue) {
+ assert(Opcode != BO_PtrMemD && Opcode != BO_PtrMemI &&
+ "Operation not supported on vector types");
+
+ const auto *VT = E->getType()->castAs<VectorType>();
+ unsigned NumElements = VT->getNumElements();
+ QualType EltTy = VT->getElementType();
+
+ // In the cases (typically C as I've observed) where we aren't evaluating
+ // constexpr but are checking for cases where the LHS isn't yet evaluatable,
+ // just give up.
+ if (!LHSValue.isVector()) {
+ assert(LHSValue.isLValue() &&
+ "A vector result that isn't a vector OR uncalculated LValue");
+ Info.FFDiag(E);
+ return false;
+ }
+
+ assert(LHSValue.getVectorLength() == NumElements &&
+ RHSValue.getVectorLength() == NumElements && "Different vector sizes");
+
+ SmallVector<APValue, 4> ResultElements;
+
+ for (unsigned EltNum = 0; EltNum < NumElements; ++EltNum) {
+ APValue LHSElt = LHSValue.getVectorElt(EltNum);
+ APValue RHSElt = RHSValue.getVectorElt(EltNum);
+
+ if (EltTy->isIntegerType()) {
+ APSInt EltResult{Info.Ctx.getIntWidth(EltTy),
+ EltTy->isUnsignedIntegerType()};
+ bool Success = true;
+
+ if (BinaryOperator::isLogicalOp(Opcode))
+ Success = handleLogicalOpForVector(LHSElt, Opcode, RHSElt, EltResult);
+ else if (BinaryOperator::isComparisonOp(Opcode))
+ Success = handleCompareOpForVector(LHSElt, Opcode, RHSElt, EltResult);
+ else
+ Success = handleIntIntBinOp(Info, E, LHSElt.getInt(), Opcode,
+ RHSElt.getInt(), EltResult);
+
+ if (!Success) {
+ Info.FFDiag(E);
+ return false;
+ }
+ ResultElements.emplace_back(EltResult);
+
+ } else if (EltTy->isFloatingType()) {
+ assert(LHSElt.getKind() == APValue::Float &&
+ RHSElt.getKind() == APValue::Float &&
+ "Mismatched LHS/RHS/Result Type");
+ APFloat LHSFloat = LHSElt.getFloat();
+
+ if (!handleFloatFloatBinOp(Info, E, LHSFloat, Opcode,
+ RHSElt.getFloat())) {
+ Info.FFDiag(E);
+ return false;
+ }
+
+ ResultElements.emplace_back(LHSFloat);
+ }
+ }
+
+ LHSValue = APValue(ResultElements.data(), ResultElements.size());
+ return true;
+}
+
/// Cast an lvalue referring to a base subobject to a derived class, by
/// truncating the lvalue's path to the given length.
static bool CastToDerivedClass(EvalInfo &Info, const Expr *E, LValue &Result,
@@ -2830,7 +3025,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
if (Info.checkingPotentialConstantExpression())
return false;
if (!Frame || !Frame->Arguments) {
- Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
+ Info.FFDiag(E, diag::note_constexpr_function_param_value_unknown) << VD;
return false;
}
Result = &Frame->Arguments[PVD->getFunctionScopeIndex()];
@@ -2861,12 +3056,34 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
}
// Dig out the initializer, and use the declaration which it's attached to.
+ // FIXME: We should eventually check whether the variable has a reachable
+ // initializing declaration.
const Expr *Init = VD->getAnyInitializer(VD);
- if (!Init || Init->isValueDependent()) {
- // If we're checking a potential constant expression, the variable could be
- // initialized later.
- if (!Info.checkingPotentialConstantExpression())
- Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
+ if (!Init) {
+ // Don't diagnose during potential constant expression checking; an
+ // initializer might be added later.
+ if (!Info.checkingPotentialConstantExpression()) {
+ Info.FFDiag(E, diag::note_constexpr_var_init_unknown, 1)
+ << VD;
+ Info.Note(VD->getLocation(), diag::note_declared_at);
+ }
+ return false;
+ }
+
+ if (Init->isValueDependent()) {
+ // The DeclRefExpr is not value-dependent, but the variable it refers to
+ // has a value-dependent initializer. This should only happen in
+ // constant-folding cases, where the variable is not actually of a suitable
+ // type for use in a constant expression (otherwise the DeclRefExpr would
+ // have been value-dependent too), so diagnose that.
+ assert(!VD->mightBeUsableInConstantExpressions(Info.Ctx));
+ if (!Info.checkingPotentialConstantExpression()) {
+ Info.FFDiag(E, Info.getLangOpts().CPlusPlus11
+ ? diag::note_constexpr_ltor_non_constexpr
+ : diag::note_constexpr_ltor_non_integral, 1)
+ << VD << VD->getType();
+ Info.Note(VD->getLocation(), diag::note_declared_at);
+ }
return false;
}
@@ -2877,13 +3094,6 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
return true;
}
- // Never evaluate the initializer of a weak variable. We can't be sure that
- // this is the definition which will be used.
- if (VD->isWeak()) {
- Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
- return false;
- }
-
// Check that we can fold the initializer. In C++, we will have already done
// this in the cases where it matters for conformance.
SmallVector<PartialDiagnosticAt, 8> Notes;
@@ -2893,13 +3103,24 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
Info.Note(VD->getLocation(), diag::note_declared_at);
Info.addNotes(Notes);
return false;
- } else if (!VD->checkInitIsICE()) {
+ }
+
+ // Check that the variable is actually usable in constant expressions.
+ if (!VD->checkInitIsICE()) {
Info.CCEDiag(E, diag::note_constexpr_var_init_non_constant,
Notes.size() + 1) << VD;
Info.Note(VD->getLocation(), diag::note_declared_at);
Info.addNotes(Notes);
}
+ // Never use the initializer of a weak variable, not even for constant
+ // folding. We can't be sure that this is the definition that will be used.
+ if (VD->isWeak()) {
+ Info.FFDiag(E, diag::note_constexpr_var_init_weak) << VD;
+ Info.Note(VD->getLocation(), diag::note_declared_at);
+ return false;
+ }
+
Result = VD->getEvaluatedValue();
return true;
}
@@ -3006,15 +3227,22 @@ static void expandArray(APValue &Array, unsigned Index) {
/// is trivial. Note that this is never true for a union type with fields
/// (because the copy always "reads" the active member) and always true for
/// a non-class type.
+static bool isReadByLvalueToRvalueConversion(const CXXRecordDecl *RD);
static bool isReadByLvalueToRvalueConversion(QualType T) {
CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
- if (!RD || (RD->isUnion() && !RD->field_empty()))
- return true;
+ return !RD || isReadByLvalueToRvalueConversion(RD);
+}
+static bool isReadByLvalueToRvalueConversion(const CXXRecordDecl *RD) {
+ // FIXME: A trivial copy of a union copies the object representation, even if
+ // the union is empty.
+ if (RD->isUnion())
+ return !RD->field_empty();
if (RD->isEmpty())
return false;
for (auto *Field : RD->fields())
- if (isReadByLvalueToRvalueConversion(Field->getType()))
+ if (!Field->isUnnamedBitfield() &&
+ isReadByLvalueToRvalueConversion(Field->getType()))
return true;
for (auto &BaseSpec : RD->bases())
@@ -3124,6 +3352,13 @@ struct CompleteObject {
: Base(Base), Value(Value), Type(Type) {}
bool mayAccessMutableMembers(EvalInfo &Info, AccessKinds AK) const {
+ // If this isn't a "real" access (eg, if it's just accessing the type
+ // info), allow it. We assume the type doesn't change dynamically for
+ // subobjects of constexpr objects (even though we'd hit UB here if it
+ // did). FIXME: Is this right?
+ if (!isAnyAccess(AK))
+ return true;
+
// In C++14 onwards, it is permitted to read a mutable member whose
// lifetime began within the evaluation.
// FIXME: Should we also allow this in C++11?
@@ -3178,9 +3413,8 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
for (unsigned I = 0, N = Sub.Entries.size(); /**/; ++I) {
// Reading an indeterminate value is undefined, but assigning over one is OK.
if ((O->isAbsent() && !(handler.AccessKind == AK_Construct && I == N)) ||
- (O->isIndeterminate() && handler.AccessKind != AK_Construct &&
- handler.AccessKind != AK_Assign &&
- handler.AccessKind != AK_ReadObjectRepresentation)) {
+ (O->isIndeterminate() &&
+ !isValidIndeterminateAccess(handler.AccessKind))) {
if (!Info.checkingPotentialConstantExpression())
Info.FFDiag(E, diag::note_constexpr_access_uninit)
<< handler.AccessKind << O->isIndeterminate();
@@ -3548,7 +3782,30 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
APValue *BaseVal = nullptr;
QualType BaseType = getType(LVal.Base);
- if (const ValueDecl *D = LVal.Base.dyn_cast<const ValueDecl*>()) {
+ if (const ConstantExpr *CE =
+ dyn_cast_or_null<ConstantExpr>(LVal.Base.dyn_cast<const Expr *>())) {
+ /// Nested immediate invocation have been previously removed so if we found
+ /// a ConstantExpr it can only be the EvaluatingDecl.
+ assert(CE->isImmediateInvocation() && CE == Info.EvaluatingDecl);
+ (void)CE;
+ BaseVal = Info.EvaluatingDeclValue;
+ } else if (const ValueDecl *D = LVal.Base.dyn_cast<const ValueDecl *>()) {
+ // Allow reading from a GUID declaration.
+ if (auto *GD = dyn_cast<MSGuidDecl>(D)) {
+ if (isModification(AK)) {
+ // All the remaining cases do not permit modification of the object.
+ Info.FFDiag(E, diag::note_constexpr_modify_global);
+ return CompleteObject();
+ }
+ APValue &V = GD->getAsAPValue();
+ if (V.isAbsent()) {
+ Info.FFDiag(E, diag::note_constexpr_unsupported_layout)
+ << GD->getType();
+ return CompleteObject();
+ }
+ return CompleteObject(LVal.Base, &V, GD->getType());
+ }
+
// In C++98, const, non-volatile integers initialized with ICEs are ICEs.
// In C++11, constexpr, non-volatile variables initialized with constant
// expressions are constant expressions too. Inside constexpr functions,
@@ -3566,6 +3823,11 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
return CompleteObject();
}
+ // In OpenCL if a variable is in constant address space it is a const value.
+ bool IsConstant = BaseType.isConstQualified() ||
+ (Info.getLangOpts().OpenCL &&
+ BaseType.getAddressSpace() == LangAS::opencl_constant);
+
// Unless we're looking at a local variable or argument in a constexpr call,
// the variable we're reading must be const.
if (!Frame) {
@@ -3583,9 +3845,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
} else if (BaseType->isIntegralOrEnumerationType()) {
// In OpenCL if a variable is in constant address space it is a const
// value.
- if (!(BaseType.isConstQualified() ||
- (Info.getLangOpts().OpenCL &&
- BaseType.getAddressSpace() == LangAS::opencl_constant))) {
+ if (!IsConstant) {
if (!IsAccess)
return CompleteObject(LVal.getLValueBase(), nullptr, BaseType);
if (Info.getLangOpts().CPlusPlus) {
@@ -3598,27 +3858,29 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
}
} else if (!IsAccess) {
return CompleteObject(LVal.getLValueBase(), nullptr, BaseType);
- } else if (BaseType->isFloatingType() && BaseType.isConstQualified()) {
- // We support folding of const floating-point types, in order to make
- // static const data members of such types (supported as an extension)
- // more useful.
- if (Info.getLangOpts().CPlusPlus11) {
- Info.CCEDiag(E, diag::note_constexpr_ltor_non_constexpr, 1) << VD;
+ } else if (IsConstant && Info.checkingPotentialConstantExpression() &&
+ BaseType->isLiteralType(Info.Ctx) && !VD->hasDefinition()) {
+ // This variable might end up being constexpr. Don't diagnose it yet.
+ } else if (IsConstant) {
+ // Keep evaluating to see what we can do. In particular, we support
+ // folding of const floating-point types, in order to make static const
+ // data members of such types (supported as an extension) more useful.
+ if (Info.getLangOpts().CPlusPlus) {
+ Info.CCEDiag(E, Info.getLangOpts().CPlusPlus11
+ ? diag::note_constexpr_ltor_non_constexpr
+ : diag::note_constexpr_ltor_non_integral, 1)
+ << VD << BaseType;
Info.Note(VD->getLocation(), diag::note_declared_at);
} else {
Info.CCEDiag(E);
}
- } else if (BaseType.isConstQualified() && VD->hasDefinition(Info.Ctx)) {
- Info.CCEDiag(E, diag::note_constexpr_ltor_non_constexpr) << VD;
- // Keep evaluating to see what we can do.
} else {
- // FIXME: Allow folding of values of any literal type in all languages.
- if (Info.checkingPotentialConstantExpression() &&
- VD->getType().isConstQualified() && !VD->hasDefinition(Info.Ctx)) {
- // The definition of this variable could be constexpr. We can't
- // access it right now, but may be able to in future.
- } else if (Info.getLangOpts().CPlusPlus11) {
- Info.FFDiag(E, diag::note_constexpr_ltor_non_constexpr, 1) << VD;
+ // Never allow reading a non-const value.
+ if (Info.getLangOpts().CPlusPlus) {
+ Info.FFDiag(E, Info.getLangOpts().CPlusPlus11
+ ? diag::note_constexpr_ltor_non_constexpr
+ : diag::note_constexpr_ltor_non_integral, 1)
+ << VD << BaseType;
Info.Note(VD->getLocation(), diag::note_declared_at);
} else {
Info.FFDiag(E);
@@ -3828,12 +4090,26 @@ struct CompoundAssignSubobjectHandler {
return false;
case APValue::LValue:
return foundPointer(Subobj, SubobjType);
+ case APValue::Vector:
+ return foundVector(Subobj, SubobjType);
default:
// FIXME: can this happen?
Info.FFDiag(E);
return false;
}
}
+
+ bool foundVector(APValue &Value, QualType SubobjType) {
+ if (!checkConst(SubobjType))
+ return false;
+
+ if (!SubobjType->isVectorType()) {
+ Info.FFDiag(E);
+ return false;
+ }
+ return handleVectorVectorBinOp(Info, E, Opcode, Value, RHS);
+ }
+
bool found(APSInt &Value, QualType SubobjType) {
if (!checkConst(SubobjType))
return false;
@@ -4230,37 +4506,48 @@ static bool HandleBaseToDerivedCast(EvalInfo &Info, const CastExpr *E,
}
/// Get the value to use for a default-initialized object of type T.
-static APValue getDefaultInitValue(QualType T) {
+/// Return false if it encounters something invalid.
+static bool getDefaultInitValue(QualType T, APValue &Result) {
+ bool Success = true;
if (auto *RD = T->getAsCXXRecordDecl()) {
- if (RD->isUnion())
- return APValue((const FieldDecl*)nullptr);
-
- APValue Struct(APValue::UninitStruct(), RD->getNumBases(),
- std::distance(RD->field_begin(), RD->field_end()));
+ if (RD->isInvalidDecl()) {
+ Result = APValue();
+ return false;
+ }
+ if (RD->isUnion()) {
+ Result = APValue((const FieldDecl *)nullptr);
+ return true;
+ }
+ Result = APValue(APValue::UninitStruct(), RD->getNumBases(),
+ std::distance(RD->field_begin(), RD->field_end()));
unsigned Index = 0;
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
- End = RD->bases_end(); I != End; ++I, ++Index)
- Struct.getStructBase(Index) = getDefaultInitValue(I->getType());
+ End = RD->bases_end();
+ I != End; ++I, ++Index)
+ Success &= getDefaultInitValue(I->getType(), Result.getStructBase(Index));
for (const auto *I : RD->fields()) {
if (I->isUnnamedBitfield())
continue;
- Struct.getStructField(I->getFieldIndex()) =
- getDefaultInitValue(I->getType());
+ Success &= getDefaultInitValue(I->getType(),
+ Result.getStructField(I->getFieldIndex()));
}
- return Struct;
+ return Success;
}
if (auto *AT =
dyn_cast_or_null<ConstantArrayType>(T->getAsArrayTypeUnsafe())) {
- APValue Array(APValue::UninitArray(), 0, AT->getSize().getZExtValue());
- if (Array.hasArrayFiller())
- Array.getArrayFiller() = getDefaultInitValue(AT->getElementType());
- return Array;
+ Result = APValue(APValue::UninitArray(), 0, AT->getSize().getZExtValue());
+ if (Result.hasArrayFiller())
+ Success &=
+ getDefaultInitValue(AT->getElementType(), Result.getArrayFiller());
+
+ return Success;
}
- return APValue::IndeterminateValue();
+ Result = APValue::IndeterminateValue();
+ return true;
}
namespace {
@@ -4290,10 +4577,8 @@ static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) {
Info.CurrentCall->createTemporary(VD, VD->getType(), true, Result);
const Expr *InitE = VD->getInit();
- if (!InitE) {
- Val = getDefaultInitValue(VD->getType());
- return true;
- }
+ if (!InitE)
+ return getDefaultInitValue(VD->getType(), Val);
if (InitE->isValueDependent())
return false;
@@ -4901,7 +5186,7 @@ static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc,
// DR1872: An instantiated virtual constexpr function can't be called in a
// constant expression (prior to C++20). We can still constant-fold such a
// call.
- if (!Info.Ctx.getLangOpts().CPlusPlus2a && isa<CXXMethodDecl>(Declaration) &&
+ if (!Info.Ctx.getLangOpts().CPlusPlus20 && isa<CXXMethodDecl>(Declaration) &&
cast<CXXMethodDecl>(Declaration)->isVirtual())
Info.CCEDiag(CallLoc, diag::note_constexpr_virtual_call);
@@ -4910,6 +5195,13 @@ static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc,
return false;
}
+ if (const auto *CtorDecl = dyn_cast_or_null<CXXConstructorDecl>(Definition)) {
+ for (const auto *InitExpr : CtorDecl->inits()) {
+ if (InitExpr->getInit() && InitExpr->getInit()->containsErrors())
+ return false;
+ }
+ }
+
// Can we evaluate this function call?
if (Definition && Definition->isConstexpr() && Body)
return true;
@@ -5060,6 +5352,7 @@ static Optional<DynamicType> ComputeDynamicType(EvalInfo &Info, const Expr *E,
case ConstructionPhase::None:
case ConstructionPhase::AfterBases:
+ case ConstructionPhase::AfterFields:
case ConstructionPhase::Destroying:
// We've finished constructing the base classes and not yet started
// destroying them again, so this is the dynamic type.
@@ -5278,12 +5571,15 @@ static bool HandleDynamicCast(EvalInfo &Info, const ExplicitCastExpr *E,
namespace {
struct StartLifetimeOfUnionMemberHandler {
+ EvalInfo &Info;
+ const Expr *LHSExpr;
const FieldDecl *Field;
-
+ bool DuringInit;
+ bool Failed = false;
static const AccessKinds AccessKind = AK_Assign;
typedef bool result_type;
- bool failed() { return false; }
+ bool failed() { return Failed; }
bool found(APValue &Subobj, QualType SubobjType) {
// We are supposed to perform no initialization but begin the lifetime of
// the object. We interpret that as meaning to do what default
@@ -5294,9 +5590,22 @@ struct StartLifetimeOfUnionMemberHandler {
// * No variant members' lifetimes begin
// * All scalar subobjects whose lifetimes begin have indeterminate values
assert(SubobjType->isUnionType());
- if (!declaresSameEntity(Subobj.getUnionField(), Field) ||
- !Subobj.getUnionValue().hasValue())
- Subobj.setUnion(Field, getDefaultInitValue(Field->getType()));
+ if (declaresSameEntity(Subobj.getUnionField(), Field)) {
+ // This union member is already active. If it's also in-lifetime, there's
+ // nothing to do.
+ if (Subobj.getUnionValue().hasValue())
+ return true;
+ } else if (DuringInit) {
+ // We're currently in the process of initializing a different union
+ // member. If we carried on, that initialization would attempt to
+ // store to an inactive union member, resulting in undefined behavior.
+ Info.FFDiag(LHSExpr,
+ diag::note_constexpr_union_member_change_during_init);
+ return false;
+ }
+ APValue Result;
+ Failed = !getDefaultInitValue(Field->getType(), Result);
+ Subobj.setUnion(Field, Result);
return true;
}
bool found(APSInt &Value, QualType SubobjType) {
@@ -5399,7 +5708,10 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr,
SubobjectDesignator D = LHS.Designator;
D.truncate(Info.Ctx, LHS.Base, LengthAndField.first);
- StartLifetimeOfUnionMemberHandler StartLifetime{LengthAndField.second};
+ bool DuringInit = Info.isEvaluatingCtorDtor(LHS.Base, D.Entries) ==
+ ConstructionPhase::AfterBases;
+ StartLifetimeOfUnionMemberHandler StartLifetime{
+ Info, LHSExpr, LengthAndField.second, DuringInit};
if (!findSubobject(Info, LHSExpr, Obj, D, StartLifetime))
return false;
}
@@ -5407,22 +5719,6 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr,
return true;
}
-/// Determine if a class has any fields that might need to be copied by a
-/// trivial copy or move operation.
-static bool hasFields(const CXXRecordDecl *RD) {
- if (!RD || RD->isEmpty())
- return false;
- for (auto *FD : RD->fields()) {
- if (FD->isUnnamedBitfield())
- continue;
- return true;
- }
- for (auto &Base : RD->bases())
- if (hasFields(Base.getType()->getAsCXXRecordDecl()))
- return true;
- return false;
-}
-
namespace {
typedef SmallVector<APValue, 8> ArgVector;
}
@@ -5447,6 +5743,8 @@ static bool EvaluateArgs(ArrayRef<const Expr *> Args, ArgVector &ArgValues,
}
}
}
+ // FIXME: This is the wrong evaluation order for an assignment operator
+ // called via operator syntax.
for (unsigned Idx = 0; Idx < Args.size(); Idx++) {
if (!Evaluate(ArgValues[Idx], Info, Args[Idx])) {
// If we're checking for a potential constant expression, evaluate all
@@ -5491,7 +5789,8 @@ static bool HandleFunctionCall(SourceLocation CallLoc,
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee);
if (MD && MD->isDefaulted() &&
(MD->getParent()->isUnion() ||
- (MD->isTrivial() && hasFields(MD->getParent())))) {
+ (MD->isTrivial() &&
+ isReadByLvalueToRvalueConversion(MD->getParent())))) {
assert(This &&
(MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()));
LValue RHS;
@@ -5500,7 +5799,7 @@ static bool HandleFunctionCall(SourceLocation CallLoc,
if (!handleLValueToRValueConversion(Info, Args[0], Args[0]->getType(), RHS,
RHSValue, MD->getParent()->isUnion()))
return false;
- if (Info.getLangOpts().CPlusPlus2a && MD->isTrivial() &&
+ if (Info.getLangOpts().CPlusPlus20 && MD->isTrivial() &&
!HandleUnionActiveMemberChange(Info, Args[0], *This))
return false;
if (!handleAssignment(Info, Args[0], *This, MD->getThisType(),
@@ -5578,7 +5877,8 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
// actually read them.
if (Definition->isDefaulted() && Definition->isCopyOrMoveConstructor() &&
(Definition->getParent()->isUnion() ||
- (Definition->isTrivial() && hasFields(Definition->getParent())))) {
+ (Definition->isTrivial() &&
+ isReadByLvalueToRvalueConversion(Definition->getParent())))) {
LValue RHS;
RHS.setFrom(Info.Ctx, ArgValues[0]);
return handleLValueToRValueConversion(
@@ -5587,9 +5887,14 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
}
// Reserve space for the struct members.
- if (!RD->isUnion() && !Result.hasValue())
- Result = APValue(APValue::UninitStruct(), RD->getNumBases(),
- std::distance(RD->field_begin(), RD->field_end()));
+ if (!Result.hasValue()) {
+ if (!RD->isUnion())
+ Result = APValue(APValue::UninitStruct(), RD->getNumBases(),
+ std::distance(RD->field_begin(), RD->field_end()));
+ else
+ // A union starts with no active member.
+ Result = APValue((const FieldDecl*)nullptr);
+ }
if (RD->isInvalidDecl()) return false;
const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD);
@@ -5616,8 +5921,9 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
for (; !declaresSameEntity(*FieldIt, FD); ++FieldIt) {
assert(FieldIt != RD->field_end() && "missing field?");
if (!FieldIt->isUnnamedBitfield())
- Result.getStructField(FieldIt->getFieldIndex()) =
- getDefaultInitValue(FieldIt->getType());
+ Success &= getDefaultInitValue(
+ FieldIt->getType(),
+ Result.getStructField(FieldIt->getFieldIndex()));
}
++FieldIt;
};
@@ -5669,10 +5975,10 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
if (CD->isUnion())
*Value = APValue(FD);
else
- // FIXME: This immediately starts the lifetime of all members of an
- // anonymous struct. It would be preferable to strictly start member
- // lifetime in initialization order.
- *Value = getDefaultInitValue(Info.Ctx.getRecordType(CD));
+ // FIXME: This immediately starts the lifetime of all members of
+ // an anonymous struct. It would be preferable to strictly start
+ // member lifetime in initialization order.
+ Success &= getDefaultInitValue(Info.Ctx.getRecordType(CD), *Value);
}
// Store Subobject as its parent before updating it for the last element
// in the chain.
@@ -5719,11 +6025,14 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
if (!RD->isUnion()) {
for (; FieldIt != RD->field_end(); ++FieldIt) {
if (!FieldIt->isUnnamedBitfield())
- Result.getStructField(FieldIt->getFieldIndex()) =
- getDefaultInitValue(FieldIt->getType());
+ Success &= getDefaultInitValue(
+ FieldIt->getType(),
+ Result.getStructField(FieldIt->getFieldIndex()));
}
}
+ EvalObj.finishedConstructingFields();
+
return Success &&
EvaluateStmt(Ret, Info, Definition->getBody()) != ESR_Failed &&
LifetimeExtendedScope.destroy();
@@ -5964,7 +6273,7 @@ static bool HandleOperatorNewCall(EvalInfo &Info, const CallExpr *E,
// This is permitted only within a call to std::allocator<T>::allocate.
auto Caller = Info.getStdAllocatorCaller("allocate");
if (!Caller) {
- Info.FFDiag(E->getExprLoc(), Info.getLangOpts().CPlusPlus2a
+ Info.FFDiag(E->getExprLoc(), Info.getLangOpts().CPlusPlus20
? diag::note_constexpr_new_untyped
: diag::note_constexpr_new);
return false;
@@ -6697,8 +7006,13 @@ public:
return Error(E);
}
- bool VisitConstantExpr(const ConstantExpr *E)
- { return StmtVisitorTy::Visit(E->getSubExpr()); }
+ bool VisitConstantExpr(const ConstantExpr *E) {
+ if (E->hasAPValueResult())
+ return DerivedSuccess(E->getAPValueResult(), E);
+
+ return StmtVisitorTy::Visit(E->getSubExpr());
+ }
+
bool VisitParenExpr(const ParenExpr *E)
{ return StmtVisitorTy::Visit(E->getSubExpr()); }
bool VisitUnaryExtension(const UnaryOperator *E)
@@ -6741,7 +7055,7 @@ public:
return static_cast<Derived*>(this)->VisitCastExpr(E);
}
bool VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E) {
- if (!Info.Ctx.getLangOpts().CPlusPlus2a)
+ if (!Info.Ctx.getLangOpts().CPlusPlus20)
CCEDiag(E, diag::note_constexpr_invalid_cast) << 1;
return static_cast<Derived*>(this)->VisitCastExpr(E);
}
@@ -6900,12 +7214,10 @@ public:
return Error(Callee);
This = &ThisVal;
} else if (const auto *PDE = dyn_cast<CXXPseudoDestructorExpr>(Callee)) {
- if (!Info.getLangOpts().CPlusPlus2a)
+ if (!Info.getLangOpts().CPlusPlus20)
Info.CCEDiag(PDE, diag::note_constexpr_pseudo_destructor);
- // FIXME: If pseudo-destructor calls ever start ending the lifetime of
- // their callee, we should start calling HandleDestruction here.
- // For now, we just evaluate the object argument and discard it.
- return EvaluateObjectArgument(Info, PDE->getBase(), ThisVal);
+ return EvaluateObjectArgument(Info, PDE->getBase(), ThisVal) &&
+ HandleDestruction(Info, PDE, ThisVal, PDE->getDestroyedType());
} else
return Error(Callee);
FD = Member;
@@ -7369,6 +7681,8 @@ public:
// from the AST (FIXME).
// * A MaterializeTemporaryExpr that has static storage duration, with no
// CallIndex, for a lifetime-extended temporary.
+// * The ConstantExpr that is currently being evaluated during evaluation of an
+// immediate invocation.
// plus an offset in bytes.
//===----------------------------------------------------------------------===//
namespace {
@@ -7448,6 +7762,8 @@ bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
return VisitVarDecl(E, VD);
if (const BindingDecl *BD = dyn_cast<BindingDecl>(E->getDecl()))
return Visit(BD->getBinding());
+ if (const MSGuidDecl *GD = dyn_cast<MSGuidDecl>(E->getDecl()))
+ return Success(GD);
return Error(E);
}
@@ -7604,7 +7920,7 @@ bool LValueExprEvaluator::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {
else
TypeInfo = TypeInfoLValue(E->getExprOperand()->getType().getTypePtr());
} else {
- if (!Info.Ctx.getLangOpts().CPlusPlus2a) {
+ if (!Info.Ctx.getLangOpts().CPlusPlus20) {
Info.CCEDiag(E, diag::note_constexpr_typeid_polymorphic)
<< E->getExprOperand()->getType()
<< E->getExprOperand()->getSourceRange();
@@ -7626,7 +7942,7 @@ bool LValueExprEvaluator::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {
}
bool LValueExprEvaluator::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
- return Success(E);
+ return Success(E->getGuidDecl());
}
bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) {
@@ -7740,7 +8056,7 @@ bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) {
if (!Evaluate(NewVal, this->Info, E->getRHS()))
return false;
- if (Info.getLangOpts().CPlusPlus2a &&
+ if (Info.getLangOpts().CPlusPlus20 &&
!HandleUnionActiveMemberChange(Info, E->getLHS(), Result))
return false;
@@ -8235,6 +8551,12 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) {
return visitNonBuiltinCallExpr(E);
}
+// Determine if T is a character type for which we guarantee that
+// sizeof(T) == 1.
+static bool isOneByteCharacterType(QualType T) {
+ return T->isCharType() || T->isChar8Type();
+}
+
bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
unsigned BuiltinOp) {
switch (BuiltinOp) {
@@ -8385,8 +8707,12 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
}
// Give up on byte-oriented matching against multibyte elements.
// FIXME: We can compare the bytes in the correct order.
- if (IsRawByte && Info.Ctx.getTypeSizeInChars(CharTy) != CharUnits::One())
+ if (IsRawByte && !isOneByteCharacterType(CharTy)) {
+ Info.FFDiag(E, diag::note_constexpr_memchr_unsupported)
+ << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'")
+ << CharTy;
return false;
+ }
// Figure out what value we're actually looking for (after converting to
// the corresponding unsigned type if necessary).
uint64_t DesiredVal;
@@ -8502,6 +8828,7 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
QualType T = Dest.Designator.getType(Info.Ctx);
QualType SrcT = Src.Designator.getType(Info.Ctx);
if (!Info.Ctx.hasSameUnqualifiedType(T, SrcT)) {
+ // FIXME: Consider using our bit_cast implementation to support this.
Info.FFDiag(E, diag::note_constexpr_memcpy_type_pun) << Move << SrcT << T;
return false;
}
@@ -8593,9 +8920,13 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
static bool EvaluateArrayNewInitList(EvalInfo &Info, LValue &This,
APValue &Result, const InitListExpr *ILE,
QualType AllocType);
+static bool EvaluateArrayNewConstructExpr(EvalInfo &Info, LValue &This,
+ APValue &Result,
+ const CXXConstructExpr *CCE,
+ QualType AllocType);
bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) {
- if (!Info.getLangOpts().CPlusPlus2a)
+ if (!Info.getLangOpts().CPlusPlus20)
Info.CCEDiag(E, diag::note_constexpr_new);
// We cannot speculatively evaluate a delete expression.
@@ -8642,6 +8973,7 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) {
const Expr *Init = E->getInitializer();
const InitListExpr *ResizedArrayILE = nullptr;
+ const CXXConstructExpr *ResizedArrayCCE = nullptr;
QualType AllocType = E->getAllocatedType();
if (Optional<const Expr*> ArraySize = E->getArraySize()) {
@@ -8685,7 +9017,7 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) {
// -- the new-initializer is a braced-init-list and the number of
// array elements for which initializers are provided [...]
// exceeds the number of elements to initialize
- if (Init) {
+ if (Init && !isa<CXXConstructExpr>(Init)) {
auto *CAT = Info.Ctx.getAsConstantArrayType(Init->getType());
assert(CAT && "unexpected type for array initializer");
@@ -8708,6 +9040,8 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) {
// special handling for this case when we initialize.
if (InitBound != AllocBound)
ResizedArrayILE = cast<InitListExpr>(Init);
+ } else if (Init) {
+ ResizedArrayCCE = cast<CXXConstructExpr>(Init);
}
AllocType = Info.Ctx.getConstantArrayType(AllocType, ArrayBound, nullptr,
@@ -8772,11 +9106,15 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) {
if (!EvaluateArrayNewInitList(Info, Result, *Val, ResizedArrayILE,
AllocType))
return false;
+ } else if (ResizedArrayCCE) {
+ if (!EvaluateArrayNewConstructExpr(Info, Result, *Val, ResizedArrayCCE,
+ AllocType))
+ return false;
} else if (Init) {
if (!EvaluateInPlace(*Val, Info, Result, Init))
return false;
- } else {
- *Val = getDefaultInitValue(AllocType);
+ } else if (!getDefaultInitValue(AllocType, *Val)) {
+ return false;
}
// Array new returns a pointer to the first element, not a pointer to the
@@ -9126,6 +9464,8 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
}
}
+ EvalObj.finishedConstructingFields();
+
return Success;
}
@@ -9145,8 +9485,7 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E,
if (ZeroInit)
return ZeroInitialization(E, T);
- Result = getDefaultInitValue(T);
- return true;
+ return getDefaultInitValue(T, Result);
}
const FunctionDecl *Definition = nullptr;
@@ -9204,24 +9543,30 @@ bool RecordExprEvaluator::VisitCXXStdInitializerListExpr(
// Get a pointer to the first element of the array.
Array.addArray(Info, E, ArrayType);
+ auto InvalidType = [&] {
+ Info.FFDiag(E, diag::note_constexpr_unsupported_layout)
+ << E->getType();
+ return false;
+ };
+
// FIXME: Perform the checks on the field types in SemaInit.
RecordDecl *Record = E->getType()->castAs<RecordType>()->getDecl();
RecordDecl::field_iterator Field = Record->field_begin();
if (Field == Record->field_end())
- return Error(E);
+ return InvalidType();
// Start pointer.
if (!Field->getType()->isPointerType() ||
!Info.Ctx.hasSameType(Field->getType()->getPointeeType(),
ArrayType->getElementType()))
- return Error(E);
+ return InvalidType();
// FIXME: What if the initializer_list type has base classes, etc?
Result = APValue(APValue::UninitStruct(), 0, 2);
Array.moveInto(Result.getStructField(0));
if (++Field == Record->field_end())
- return Error(E);
+ return InvalidType();
if (Field->getType()->isPointerType() &&
Info.Ctx.hasSameType(Field->getType()->getPointeeType(),
@@ -9236,10 +9581,10 @@ bool RecordExprEvaluator::VisitCXXStdInitializerListExpr(
// Length.
Result.getStructField(1) = APValue(APSInt(ArrayType->getSize()));
else
- return Error(E);
+ return InvalidType();
if (++Field != Record->field_end())
- return Error(E);
+ return InvalidType();
return true;
}
@@ -9376,10 +9721,9 @@ namespace {
bool VisitCastExpr(const CastExpr* E);
bool VisitInitListExpr(const InitListExpr *E);
bool VisitUnaryImag(const UnaryOperator *E);
- // FIXME: Missing: unary -, unary ~, binary add/sub/mul/div,
- // binary comparisons, binary and/or/xor,
- // conditional operator (for GNU conditional select),
- // shufflevector, ExtVectorElementExpr
+ bool VisitBinaryOperator(const BinaryOperator *E);
+ // FIXME: Missing: unary -, unary ~, conditional operator (for GNU
+ // conditional select), shufflevector, ExtVectorElementExpr
};
} // end anonymous namespace
@@ -9527,6 +9871,41 @@ bool VectorExprEvaluator::VisitUnaryImag(const UnaryOperator *E) {
return ZeroInitialization(E);
}
+bool VectorExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
+ BinaryOperatorKind Op = E->getOpcode();
+ assert(Op != BO_PtrMemD && Op != BO_PtrMemI && Op != BO_Cmp &&
+ "Operation not supported on vector types");
+
+ if (Op == BO_Comma)
+ return ExprEvaluatorBaseTy::VisitBinaryOperator(E);
+
+ Expr *LHS = E->getLHS();
+ Expr *RHS = E->getRHS();
+
+ assert(LHS->getType()->isVectorType() && RHS->getType()->isVectorType() &&
+ "Must both be vector types");
+ // Checking JUST the types are the same would be fine, except shifts don't
+ // need to have their types be the same (since you always shift by an int).
+ assert(LHS->getType()->getAs<VectorType>()->getNumElements() ==
+ E->getType()->getAs<VectorType>()->getNumElements() &&
+ RHS->getType()->getAs<VectorType>()->getNumElements() ==
+ E->getType()->getAs<VectorType>()->getNumElements() &&
+ "All operands must be the same size.");
+
+ APValue LHSValue;
+ APValue RHSValue;
+ bool LHSOK = Evaluate(LHSValue, Info, LHS);
+ if (!LHSOK && !Info.noteFailure())
+ return false;
+ if (!Evaluate(RHSValue, Info, RHS) || !LHSOK)
+ return false;
+
+ if (!handleVectorVectorBinOp(Info, E, Op, LHSValue, RHSValue))
+ return false;
+
+ return Success(LHSValue, E);
+}
+
//===----------------------------------------------------------------------===//
// Array Evaluation
//===----------------------------------------------------------------------===//
@@ -9550,8 +9929,18 @@ namespace {
bool ZeroInitialization(const Expr *E) {
const ConstantArrayType *CAT =
Info.Ctx.getAsConstantArrayType(E->getType());
- if (!CAT)
+ if (!CAT) {
+ if (const IncompleteArrayType *IAT =
+ Info.Ctx.getAsIncompleteArrayType(E->getType())) {
+ // We can be asked to zero-initialize a flexible array member; this
+ // is represented as an ImplicitValueInitExpr of incomplete array
+ // type. In this case, the array has zero elements.
+ Result = APValue(APValue::UninitArray(), 0, 0);
+ return true;
+ }
+ // FIXME: We could handle VLAs here.
return Error(E);
+ }
Result = APValue(APValue::UninitArray(), 0,
CAT->getSize().getZExtValue());
@@ -9597,9 +9986,19 @@ static bool EvaluateArrayNewInitList(EvalInfo &Info, LValue &This,
.VisitInitListExpr(ILE, AllocType);
}
+static bool EvaluateArrayNewConstructExpr(EvalInfo &Info, LValue &This,
+ APValue &Result,
+ const CXXConstructExpr *CCE,
+ QualType AllocType) {
+ assert(CCE->isRValue() && CCE->getType()->isArrayType() &&
+ "not an array rvalue");
+ return ArrayExprEvaluator(Info, This, Result)
+ .VisitCXXConstructExpr(CCE, This, &Result, AllocType);
+}
+
// Return true iff the given array filler may depend on the element index.
static bool MaybeElementDependentArrayFiller(const Expr *FillerExpr) {
- // For now, just whitelist non-class value-initialization and initialization
+ // For now, just allow non-class value-initialization and initialization
// lists comprised of them.
if (isa<ImplicitValueInitExpr>(FillerExpr))
return false;
@@ -9836,8 +10235,6 @@ public:
// Visitor Methods
//===--------------------------------------------------------------------===//
- bool VisitConstantExpr(const ConstantExpr *E);
-
bool VisitIntegerLiteral(const IntegerLiteral *E) {
return Success(E->getValue(), E);
}
@@ -9912,6 +10309,7 @@ public:
bool VisitSizeOfPackExpr(const SizeOfPackExpr *E);
bool VisitSourceLocExpr(const SourceLocExpr *E);
bool VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E);
+ bool VisitRequiresExpr(const RequiresExpr *E);
// FIXME: Missing: array subscript of vector, member of vector
};
@@ -10199,10 +10597,12 @@ EvaluateBuiltinClassifyType(QualType T, const LangOptions &LangOpts) {
case Type::BlockPointer:
case Type::Vector:
case Type::ExtVector:
+ case Type::ConstantMatrix:
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
case Type::Pipe:
+ case Type::ExtInt:
// GCC classifies vectors as None. We follow its lead and classify all
// other types that don't fit into the regular classification the same way.
return GCCTypeClass::None;
@@ -10286,7 +10686,7 @@ static bool EvaluateBuiltinConstantP(EvalInfo &Info, const Expr *Arg) {
ArgType->isAnyComplexType() || ArgType->isPointerType() ||
ArgType->isNullPtrType()) {
APValue V;
- if (!::EvaluateAsRValue(Info, Arg, V)) {
+ if (!::EvaluateAsRValue(Info, Arg, V) || Info.EvalStatus.HasSideEffects) {
Fold.keepDiagnostics();
return false;
}
@@ -10464,9 +10864,9 @@ static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const LValue &LVal) {
// the array at the end was flexible, or if it had 0 or 1 elements. This
// broke some common standard library extensions (PR30346), but was
// otherwise seemingly fine. It may be useful to reintroduce this behavior
- // with some sort of whitelist. OTOH, it seems that GCC is always
+ // with some sort of list. OTOH, it seems that GCC is always
// conservative with the last element in structs (if it's an array), so our
- // current behavior is more compatible than a whitelisting approach would
+ // current behavior is more compatible than an explicit list approach would
// be.
return LVal.InvalidBase &&
Designator.Entries.size() == Designator.MostDerivedPathLength &&
@@ -10616,13 +11016,6 @@ static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type,
return true;
}
-bool IntExprEvaluator::VisitConstantExpr(const ConstantExpr *E) {
- llvm::SaveAndRestore<bool> InConstantContext(Info.InConstantContext, true);
- if (E->getResultAPValueKind() != APValue::None)
- return Success(E->getAPValueResult(), E);
- return ExprEvaluatorBaseTy::VisitConstantExpr(E);
-}
-
bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
if (unsigned BuiltinOp = E->getBuiltinCallee())
return VisitBuiltinCallExpr(E, BuiltinOp);
@@ -10659,7 +11052,7 @@ static bool getBuiltinAlignArguments(const CallExpr *E, EvalInfo &Info,
bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
unsigned BuiltinOp) {
- switch (unsigned BuiltinOp = E->getBuiltinCallee()) {
+ switch (BuiltinOp) {
default:
return ExprEvaluatorBaseTy::VisitCallExpr(E);
@@ -10848,6 +11241,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
}
case Builtin::BI__builtin_expect:
+ case Builtin::BI__builtin_expect_with_probability:
return Visit(E->getArg(0));
case Builtin::BI__builtin_ffs:
@@ -11041,6 +11435,17 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
CharTy1, E->getArg(0)->getType()->getPointeeType()) &&
Info.Ctx.hasSameUnqualifiedType(CharTy1, CharTy2)));
+ // For memcmp, allow comparing any arrays of '[[un]signed] char' or
+ // 'char8_t', but no other types.
+ if (IsRawByte &&
+ !(isOneByteCharacterType(CharTy1) && isOneByteCharacterType(CharTy2))) {
+ // FIXME: Consider using our bit_cast implementation to support this.
+ Info.FFDiag(E, diag::note_constexpr_memcmp_unsupported)
+ << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'")
+ << CharTy1 << CharTy2;
+ return false;
+ }
+
const auto &ReadCurElems = [&](APValue &Char1, APValue &Char2) {
return handleLValueToRValueConversion(Info, E, CharTy1, String1, Char1) &&
handleLValueToRValueConversion(Info, E, CharTy2, String2, Char2) &&
@@ -11051,57 +11456,6 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
HandleLValueArrayAdjustment(Info, E, String2, CharTy2, 1);
};
- if (IsRawByte) {
- uint64_t BytesRemaining = MaxLength;
- // Pointers to const void may point to objects of incomplete type.
- if (CharTy1->isIncompleteType()) {
- Info.FFDiag(E, diag::note_constexpr_ltor_incomplete_type) << CharTy1;
- return false;
- }
- if (CharTy2->isIncompleteType()) {
- Info.FFDiag(E, diag::note_constexpr_ltor_incomplete_type) << CharTy2;
- return false;
- }
- uint64_t CharTy1Width{Info.Ctx.getTypeSize(CharTy1)};
- CharUnits CharTy1Size = Info.Ctx.toCharUnitsFromBits(CharTy1Width);
- // Give up on comparing between elements with disparate widths.
- if (CharTy1Size != Info.Ctx.getTypeSizeInChars(CharTy2))
- return false;
- uint64_t BytesPerElement = CharTy1Size.getQuantity();
- assert(BytesRemaining && "BytesRemaining should not be zero: the "
- "following loop considers at least one element");
- while (true) {
- APValue Char1, Char2;
- if (!ReadCurElems(Char1, Char2))
- return false;
- // We have compatible in-memory widths, but a possible type and
- // (for `bool`) internal representation mismatch.
- // Assuming two's complement representation, including 0 for `false` and
- // 1 for `true`, we can check an appropriate number of elements for
- // equality even if they are not byte-sized.
- APSInt Char1InMem = Char1.getInt().extOrTrunc(CharTy1Width);
- APSInt Char2InMem = Char2.getInt().extOrTrunc(CharTy1Width);
- if (Char1InMem.ne(Char2InMem)) {
- // If the elements are byte-sized, then we can produce a three-way
- // comparison result in a straightforward manner.
- if (BytesPerElement == 1u) {
- // memcmp always compares unsigned chars.
- return Success(Char1InMem.ult(Char2InMem) ? -1 : 1, E);
- }
- // The result is byte-order sensitive, and we have multibyte elements.
- // FIXME: We can compare the remaining bytes in the correct order.
- return false;
- }
- if (!AdvanceElems())
- return false;
- if (BytesRemaining <= BytesPerElement)
- break;
- BytesRemaining -= BytesPerElement;
- }
- // Enough elements are equal to account for the memcmp limit.
- return Success(0, E);
- }
-
bool StopAtNull =
(BuiltinOp != Builtin::BImemcmp && BuiltinOp != Builtin::BIbcmp &&
BuiltinOp != Builtin::BIwmemcmp &&
@@ -11119,7 +11473,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
APValue Char1, Char2;
if (!ReadCurElems(Char1, Char2))
return false;
- if (Char1.getInt() != Char2.getInt()) {
+ if (Char1.getInt().ne(Char2.getInt())) {
if (IsWide) // wmemcmp compares with wchar_t signedness.
return Success(Char1.getInt() < Char2.getInt() ? -1 : 1, E);
// memcmp always compares unsigned chars.
@@ -12524,6 +12878,9 @@ bool IntExprEvaluator::VisitConceptSpecializationExpr(
return Success(E->isSatisfied(), E);
}
+bool IntExprEvaluator::VisitRequiresExpr(const RequiresExpr *E) {
+ return Success(E->isSatisfied(), E);
+}
bool FixedPointExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
switch (E->getOpcode()) {
@@ -12566,8 +12923,14 @@ bool FixedPointExprEvaluator::VisitCastExpr(const CastExpr *E) {
return false;
bool Overflowed;
APFixedPoint Result = Src.convert(DestFXSema, &Overflowed);
- if (Overflowed && !HandleOverflow(Info, E, Result, DestType))
- return false;
+ if (Overflowed) {
+ if (Info.checkingForUndefinedBehavior())
+ Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
+ diag::warn_fixedpoint_constant_overflow)
+ << Result.toString() << E->getType();
+ else if (!HandleOverflow(Info, E, Result, E->getType()))
+ return false;
+ }
return Success(Result, E);
}
case CK_IntegralToFixedPoint: {
@@ -12579,8 +12942,14 @@ bool FixedPointExprEvaluator::VisitCastExpr(const CastExpr *E) {
APFixedPoint IntResult = APFixedPoint::getFromIntValue(
Src, Info.Ctx.getFixedPointSemantics(DestType), &Overflowed);
- if (Overflowed && !HandleOverflow(Info, E, IntResult, DestType))
- return false;
+ if (Overflowed) {
+ if (Info.checkingForUndefinedBehavior())
+ Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
+ diag::warn_fixedpoint_constant_overflow)
+ << IntResult.toString() << E->getType();
+ else if (!HandleOverflow(Info, E, IntResult, E->getType()))
+ return false;
+ }
return Success(IntResult, E);
}
@@ -12593,6 +12962,9 @@ bool FixedPointExprEvaluator::VisitCastExpr(const CastExpr *E) {
}
bool FixedPointExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
+ if (E->isPtrMemOp() || E->isAssignmentOp() || E->getOpcode() == BO_Comma)
+ return ExprEvaluatorBaseTy::VisitBinaryOperator(E);
+
const Expr *LHS = E->getLHS();
const Expr *RHS = E->getRHS();
FixedPointSemantics ResultFXSema =
@@ -12605,20 +12977,45 @@ bool FixedPointExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
if (!EvaluateFixedPointOrInteger(RHS, RHSFX, Info))
return false;
+ bool OpOverflow = false, ConversionOverflow = false;
+ APFixedPoint Result(LHSFX.getSemantics());
switch (E->getOpcode()) {
case BO_Add: {
- bool AddOverflow, ConversionOverflow;
- APFixedPoint Result = LHSFX.add(RHSFX, &AddOverflow)
- .convert(ResultFXSema, &ConversionOverflow);
- if ((AddOverflow || ConversionOverflow) &&
- !HandleOverflow(Info, E, Result, E->getType()))
+ Result = LHSFX.add(RHSFX, &OpOverflow)
+ .convert(ResultFXSema, &ConversionOverflow);
+ break;
+ }
+ case BO_Sub: {
+ Result = LHSFX.sub(RHSFX, &OpOverflow)
+ .convert(ResultFXSema, &ConversionOverflow);
+ break;
+ }
+ case BO_Mul: {
+ Result = LHSFX.mul(RHSFX, &OpOverflow)
+ .convert(ResultFXSema, &ConversionOverflow);
+ break;
+ }
+ case BO_Div: {
+ if (RHSFX.getValue() == 0) {
+ Info.FFDiag(E, diag::note_expr_divide_by_zero);
return false;
- return Success(Result, E);
+ }
+ Result = LHSFX.div(RHSFX, &OpOverflow)
+ .convert(ResultFXSema, &ConversionOverflow);
+ break;
}
default:
return false;
}
- llvm_unreachable("Should've exited before this");
+ if (OpOverflow || ConversionOverflow) {
+ if (Info.checkingForUndefinedBehavior())
+ Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
+ diag::warn_fixedpoint_constant_overflow)
+ << Result.toString() << E->getType();
+ else if (!HandleOverflow(Info, E, Result, E->getType()))
+ return false;
+ }
+ return Success(Result, E);
}
//===----------------------------------------------------------------------===//
@@ -13470,7 +13867,7 @@ bool VoidExprEvaluator::VisitCXXDeleteExpr(const CXXDeleteExpr *E) {
// This is the only case where we need to produce an extension warning:
// the only other way we can succeed is if we find a dynamic allocation,
// and we will have warned when we allocated it in that case.
- if (!Info.getLangOpts().CPlusPlus2a)
+ if (!Info.getLangOpts().CPlusPlus20)
Info.CCEDiag(E, diag::note_constexpr_new);
return true;
}
@@ -13823,7 +14220,7 @@ bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx,
}
bool Expr::EvaluateAsConstantExpr(EvalResult &Result, ConstExprUsage Usage,
- const ASTContext &Ctx) const {
+ const ASTContext &Ctx, bool InPlace) const {
assert(!isValueDependent() &&
"Expression evaluator can't be called on a dependent expression.");
@@ -13831,7 +14228,14 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, ConstExprUsage Usage,
EvalInfo Info(Ctx, Result, EM);
Info.InConstantContext = true;
- if (!::Evaluate(Result.Val, Info, this) || Result.HasSideEffects)
+ if (InPlace) {
+ Info.setEvaluatingDecl(this, Result.Val);
+ LValue LVal;
+ LVal.set(this);
+ if (!::EvaluateInPlace(Result.Val, Info, LVal, this) ||
+ Result.HasSideEffects)
+ return false;
+ } else if (!::Evaluate(Result.Val, Info, this) || Result.HasSideEffects)
return false;
if (!Info.discardCleanups())
@@ -13874,18 +14278,6 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
LValue LVal;
LVal.set(VD);
- // C++11 [basic.start.init]p2:
- // Variables with static storage duration or thread storage duration shall
- // be zero-initialized before any other initialization takes place.
- // This behavior is not present in C.
- if (Ctx.getLangOpts().CPlusPlus && !VD->hasLocalStorage() &&
- !DeclTy->isReferenceType()) {
- ImplicitValueInitExpr VIE(DeclTy);
- if (!EvaluateInPlace(Value, Info, LVal, &VIE,
- /*AllowNonLiteralTypes=*/true))
- return false;
- }
-
if (!EvaluateInPlace(Value, Info, LVal, this,
/*AllowNonLiteralTypes=*/true) ||
EStatus.HasSideEffects)
@@ -13904,14 +14296,17 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
bool VarDecl::evaluateDestruction(
SmallVectorImpl<PartialDiagnosticAt> &Notes) const {
- assert(getEvaluatedValue() && !getEvaluatedValue()->isAbsent() &&
- "cannot evaluate destruction of non-constant-initialized variable");
-
Expr::EvalStatus EStatus;
EStatus.Diag = &Notes;
- // Make a copy of the value for the destructor to mutate.
- APValue DestroyedValue = *getEvaluatedValue();
+ // Make a copy of the value for the destructor to mutate, if we know it.
+ // Otherwise, treat the value as default-initialized; if the destructor works
+ // anyway, then the destruction is constant (and must be essentially empty).
+ APValue DestroyedValue;
+ if (getEvaluatedValue() && !getEvaluatedValue()->isAbsent())
+ DestroyedValue = *getEvaluatedValue();
+ else if (!getDefaultInitValue(getType(), DestroyedValue))
+ return false;
EvalInfo Info(getASTContext(), EStatus, EvalInfo::EM_ConstantExpression);
Info.setEvaluatingDecl(this, DestroyedValue,
@@ -13924,8 +14319,6 @@ bool VarDecl::evaluateDestruction(
LValue LVal;
LVal.set(this);
- // FIXME: Consider storing whether this variable has constant destruction in
- // the EvaluatedStmt so that CodeGen can query it.
if (!HandleDestruction(Info, DeclLoc, LVal.Base, DestroyedValue, DeclTy) ||
EStatus.HasSideEffects)
return false;
@@ -14073,7 +14466,10 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::ImaginaryLiteralClass:
case Expr::StringLiteralClass:
case Expr::ArraySubscriptExprClass:
+ case Expr::MatrixSubscriptExprClass:
case Expr::OMPArraySectionExprClass:
+ case Expr::OMPArrayShapingExprClass:
+ case Expr::OMPIteratorExprClass:
case Expr::MemberExprClass:
case Expr::CompoundAssignOperatorClass:
case Expr::CompoundLiteralExprClass:
@@ -14090,6 +14486,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::StmtExprClass:
case Expr::CXXMemberCallExprClass:
case Expr::CUDAKernelCallExprClass:
+ case Expr::CXXAddrspaceCastExprClass:
case Expr::CXXDynamicCastExprClass:
case Expr::CXXTypeidExprClass:
case Expr::CXXUuidofExprClass:
@@ -14104,6 +14501,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::CXXPseudoDestructorExprClass:
case Expr::UnresolvedLookupExprClass:
case Expr::TypoExprClass:
+ case Expr::RecoveryExprClass:
case Expr::DependentScopeDeclRefExprClass:
case Expr::CXXConstructExprClass:
case Expr::CXXInheritedCtorInitExprClass:
@@ -14182,6 +14580,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::CXXScalarValueInitExprClass:
case Expr::TypeTraitExprClass:
case Expr::ConceptSpecializationExprClass:
+ case Expr::RequiresExprClass:
case Expr::ArrayTypeTraitExprClass:
case Expr::ExpressionTraitExprClass:
case Expr::CXXNoexceptExprClass:
@@ -14627,6 +15026,15 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD,
if (FD->isDependentContext())
return true;
+ // Bail out if a constexpr constructor has an initializer that contains an
+ // error. We deliberately don't produce a diagnostic, as we have produced a
+ // relevant diagnostic when parsing the error initializer.
+ if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(FD)) {
+ for (const auto *InitExpr : Ctor->inits()) {
+ if (InitExpr->getInit() && InitExpr->getInit()->containsErrors())
+ return false;
+ }
+ }
Expr::EvalStatus Status;
Status.Diag = &Diags;
diff --git a/clang/lib/AST/ExprObjC.cpp b/clang/lib/AST/ExprObjC.cpp
index 53d0e873f8c9e..662bc325f12c8 100644
--- a/clang/lib/AST/ExprObjC.cpp
+++ b/clang/lib/AST/ExprObjC.cpp
@@ -12,6 +12,8 @@
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ComputeDependence.h"
+#include "clang/AST/DependenceFlags.h"
#include "clang/AST/SelectorLocationsKind.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
@@ -25,20 +27,13 @@ using namespace clang;
ObjCArrayLiteral::ObjCArrayLiteral(ArrayRef<Expr *> Elements, QualType T,
ObjCMethodDecl *Method, SourceRange SR)
- : Expr(ObjCArrayLiteralClass, T, VK_RValue, OK_Ordinary, false, false,
- false, false),
+ : Expr(ObjCArrayLiteralClass, T, VK_RValue, OK_Ordinary),
NumElements(Elements.size()), Range(SR), ArrayWithObjectsMethod(Method) {
Expr **SaveElements = getElements();
- for (unsigned I = 0, N = Elements.size(); I != N; ++I) {
- if (Elements[I]->isTypeDependent() || Elements[I]->isValueDependent())
- ExprBits.ValueDependent = true;
- if (Elements[I]->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- if (Elements[I]->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
-
+ for (unsigned I = 0, N = Elements.size(); I != N; ++I)
SaveElements[I] = Elements[I];
- }
+
+ setDependence(computeDependence(this));
}
ObjCArrayLiteral *ObjCArrayLiteral::Create(const ASTContext &C,
@@ -59,25 +54,13 @@ ObjCDictionaryLiteral::ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK,
bool HasPackExpansions, QualType T,
ObjCMethodDecl *method,
SourceRange SR)
- : Expr(ObjCDictionaryLiteralClass, T, VK_RValue, OK_Ordinary, false, false,
- false, false),
+ : Expr(ObjCDictionaryLiteralClass, T, VK_RValue, OK_Ordinary),
NumElements(VK.size()), HasPackExpansions(HasPackExpansions), Range(SR),
DictWithObjectsMethod(method) {
KeyValuePair *KeyValues = getTrailingObjects<KeyValuePair>();
ExpansionData *Expansions =
HasPackExpansions ? getTrailingObjects<ExpansionData>() : nullptr;
for (unsigned I = 0; I < NumElements; I++) {
- if (VK[I].Key->isTypeDependent() || VK[I].Key->isValueDependent() ||
- VK[I].Value->isTypeDependent() || VK[I].Value->isValueDependent())
- ExprBits.ValueDependent = true;
- if (VK[I].Key->isInstantiationDependent() ||
- VK[I].Value->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- if (VK[I].EllipsisLoc.isInvalid() &&
- (VK[I].Key->containsUnexpandedParameterPack() ||
- VK[I].Value->containsUnexpandedParameterPack()))
- ExprBits.ContainsUnexpandedParameterPack = true;
-
KeyValues[I].Key = VK[I].Key;
KeyValues[I].Value = VK[I].Value;
if (Expansions) {
@@ -88,6 +71,7 @@ ObjCDictionaryLiteral::ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK,
Expansions[I].NumExpansionsPlusOne = 0;
}
}
+ setDependence(computeDependence(this));
}
ObjCDictionaryLiteral *
@@ -127,10 +111,7 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method, ArrayRef<Expr *> Args,
SourceLocation RBracLoc, bool isImplicit)
- : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary,
- /*TypeDependent=*/false, /*ValueDependent=*/false,
- /*InstantiationDependent=*/false,
- /*ContainsUnexpandedParameterPack=*/false),
+ : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary),
SelectorOrMethod(
reinterpret_cast<uintptr_t>(Method ? Method : Sel.getAsOpaquePtr())),
Kind(IsInstanceSuper ? SuperInstance : SuperClass),
@@ -139,6 +120,7 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK,
RBracLoc(RBracLoc) {
initArgsAndSelLocs(Args, SelLocs, SelLocsK);
setReceiverPointer(SuperType.getAsOpaquePtr());
+ setDependence(computeDependence(this));
}
ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK,
@@ -148,15 +130,14 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method, ArrayRef<Expr *> Args,
SourceLocation RBracLoc, bool isImplicit)
- : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, T->isDependentType(),
- T->isDependentType(), T->isInstantiationDependentType(),
- T->containsUnexpandedParameterPack()),
+ : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary),
SelectorOrMethod(
reinterpret_cast<uintptr_t>(Method ? Method : Sel.getAsOpaquePtr())),
Kind(Class), HasMethod(Method != nullptr), IsDelegateInitCall(false),
IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc) {
initArgsAndSelLocs(Args, SelLocs, SelLocsK);
setReceiverPointer(Receiver);
+ setDependence(computeDependence(this));
}
ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK,
@@ -165,16 +146,14 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method, ArrayRef<Expr *> Args,
SourceLocation RBracLoc, bool isImplicit)
- : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary,
- Receiver->isTypeDependent(), Receiver->isTypeDependent(),
- Receiver->isInstantiationDependent(),
- Receiver->containsUnexpandedParameterPack()),
+ : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary),
SelectorOrMethod(
reinterpret_cast<uintptr_t>(Method ? Method : Sel.getAsOpaquePtr())),
Kind(Instance), HasMethod(Method != nullptr), IsDelegateInitCall(false),
IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc) {
initArgsAndSelLocs(Args, SelLocs, SelLocsK);
setReceiverPointer(Receiver);
+ setDependence(computeDependence(this));
}
void ObjCMessageExpr::initArgsAndSelLocs(ArrayRef<Expr *> Args,
@@ -182,18 +161,8 @@ void ObjCMessageExpr::initArgsAndSelLocs(ArrayRef<Expr *> Args,
SelectorLocationsKind SelLocsK) {
setNumArgs(Args.size());
Expr **MyArgs = getArgs();
- for (unsigned I = 0; I != Args.size(); ++I) {
- if (Args[I]->isTypeDependent())
- ExprBits.TypeDependent = true;
- if (Args[I]->isValueDependent())
- ExprBits.ValueDependent = true;
- if (Args[I]->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- if (Args[I]->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
-
+ for (unsigned I = 0; I != Args.size(); ++I)
MyArgs[I] = Args[I];
- }
SelLocsKind = SelLocsK;
if (!isImplicit()) {
diff --git a/clang/lib/AST/ExternalASTSource.cpp b/clang/lib/AST/ExternalASTSource.cpp
index 837be5527fce3..2578331826215 100644
--- a/clang/lib/AST/ExternalASTSource.cpp
+++ b/clang/lib/AST/ExternalASTSource.cpp
@@ -15,9 +15,11 @@
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclarationName.h"
+#include "clang/Basic/FileManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/None.h"
#include "llvm/Support/ErrorHandling.h"
#include <cstdint>
@@ -28,7 +30,7 @@ char ExternalASTSource::ID;
ExternalASTSource::~ExternalASTSource() = default;
-llvm::Optional<ExternalASTSource::ASTSourceDescriptor>
+llvm::Optional<ASTSourceDescriptor>
ExternalASTSource::getSourceDescriptor(unsigned ID) {
return None;
}
@@ -38,21 +40,6 @@ ExternalASTSource::hasExternalDefinitions(const Decl *D) {
return EK_ReplyHazy;
}
-ExternalASTSource::ASTSourceDescriptor::ASTSourceDescriptor(const Module &M)
- : Signature(M.Signature), ClangModule(&M) {
- if (M.Directory)
- Path = M.Directory->getName();
- if (auto *File = M.getASTFile())
- ASTFile = File->getName();
-}
-
-std::string ExternalASTSource::ASTSourceDescriptor::getModuleName() const {
- if (ClangModule)
- return ClangModule->Name;
- else
- return PCHModuleName;
-}
-
void ExternalASTSource::FindFileRegionDecls(FileID File, unsigned Offset,
unsigned Length,
SmallVectorImpl<Decl *> &Decls) {}
diff --git a/clang/lib/AST/FormatString.cpp b/clang/lib/AST/FormatString.cpp
index fcc0b3b11e259..83b952116a5e0 100644
--- a/clang/lib/AST/FormatString.cpp
+++ b/clang/lib/AST/FormatString.cpp
@@ -419,7 +419,6 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const {
QualType pointeeTy = PT->getPointeeType();
if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())
switch (BT->getKind()) {
- case BuiltinType::Void:
case BuiltinType::Char_U:
case BuiltinType::UChar:
case BuiltinType::Char_S:
@@ -539,7 +538,7 @@ QualType ArgType::getRepresentativeType(ASTContext &C) const {
}
std::string ArgType::getRepresentativeTypeName(ASTContext &C) const {
- std::string S = getRepresentativeType(C).getAsString();
+ std::string S = getRepresentativeType(C).getAsString(C.getPrintingPolicy());
std::string Alias;
if (Name) {
diff --git a/clang/lib/AST/Interp/Boolean.h b/clang/lib/AST/Interp/Boolean.h
index 3e6c8b5da9f05..2baa717311bc4 100644
--- a/clang/lib/AST/Interp/Boolean.h
+++ b/clang/lib/AST/Interp/Boolean.h
@@ -85,14 +85,13 @@ class Boolean {
static Boolean max(unsigned NumBits) { return Boolean(true); }
template <typename T>
- static typename std::enable_if<std::is_integral<T>::value, Boolean>::type
- from(T Value) {
+ static std::enable_if_t<std::is_integral<T>::value, Boolean> from(T Value) {
return Boolean(Value != 0);
}
template <unsigned SrcBits, bool SrcSign>
- static typename std::enable_if<SrcBits != 0, Boolean>::type from(
- Integral<SrcBits, SrcSign> Value) {
+ static std::enable_if_t<SrcBits != 0, Boolean>
+ from(Integral<SrcBits, SrcSign> Value) {
return Boolean(!Value.isZero());
}
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h
index 1d0e34fc991f2..716f28551e58e 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.h
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -21,6 +21,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/Optional.h"
namespace clang {
diff --git a/clang/lib/AST/Interp/Context.cpp b/clang/lib/AST/Interp/Context.cpp
index e7f9ba0f010ae..3bfcdfcd4c58e 100644
--- a/clang/lib/AST/Interp/Context.cpp
+++ b/clang/lib/AST/Interp/Context.cpp
@@ -17,6 +17,7 @@
#include "PrimType.h"
#include "Program.h"
#include "clang/AST/Expr.h"
+#include "clang/Basic/TargetInfo.h"
using namespace clang;
using namespace clang::interp;
diff --git a/clang/lib/AST/Interp/Disasm.cpp b/clang/lib/AST/Interp/Disasm.cpp
index e77a825eb1f23..293fdd4b3256e 100644
--- a/clang/lib/AST/Interp/Disasm.cpp
+++ b/clang/lib/AST/Interp/Disasm.cpp
@@ -16,6 +16,7 @@
#include "Program.h"
#include "clang/AST/DeclCXX.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Format.h"
using namespace clang;
using namespace clang::interp;
diff --git a/clang/lib/AST/Interp/Integral.h b/clang/lib/AST/Interp/Integral.h
index 7cc788070de84..46cd611ee3892 100644
--- a/clang/lib/AST/Interp/Integral.h
+++ b/clang/lib/AST/Interp/Integral.h
@@ -156,13 +156,12 @@ public:
}
template <typename T>
- static typename std::enable_if<std::is_integral<T>::value, Integral>::type
- from(T Value) {
+ static std::enable_if_t<std::is_integral<T>::value, Integral> from(T Value) {
return Integral(Value);
}
template <unsigned SrcBits, bool SrcSign>
- static typename std::enable_if<SrcBits != 0, Integral>::type
+ static std::enable_if_t<SrcBits != 0, Integral>
from(Integral<SrcBits, SrcSign> Value) {
return Integral(Value.V);
}
@@ -206,52 +205,52 @@ public:
private:
template <typename T>
- static typename std::enable_if<std::is_signed<T>::value, bool>::type
- CheckAddUB(T A, T B, T &R) {
+ static std::enable_if_t<std::is_signed<T>::value, bool> CheckAddUB(T A, T B,
+ T &R) {
return llvm::AddOverflow<T>(A, B, R);
}
template <typename T>
- static typename std::enable_if<std::is_unsigned<T>::value, bool>::type
- CheckAddUB(T A, T B, T &R) {
+ static std::enable_if_t<std::is_unsigned<T>::value, bool> CheckAddUB(T A, T B,
+ T &R) {
R = A + B;
return false;
}
template <typename T>
- static typename std::enable_if<std::is_signed<T>::value, bool>::type
- CheckSubUB(T A, T B, T &R) {
+ static std::enable_if_t<std::is_signed<T>::value, bool> CheckSubUB(T A, T B,
+ T &R) {
return llvm::SubOverflow<T>(A, B, R);
}
template <typename T>
- static typename std::enable_if<std::is_unsigned<T>::value, bool>::type
- CheckSubUB(T A, T B, T &R) {
+ static std::enable_if_t<std::is_unsigned<T>::value, bool> CheckSubUB(T A, T B,
+ T &R) {
R = A - B;
return false;
}
template <typename T>
- static typename std::enable_if<std::is_signed<T>::value, bool>::type
- CheckMulUB(T A, T B, T &R) {
+ static std::enable_if_t<std::is_signed<T>::value, bool> CheckMulUB(T A, T B,
+ T &R) {
return llvm::MulOverflow<T>(A, B, R);
}
template <typename T>
- static typename std::enable_if<std::is_unsigned<T>::value, bool>::type
- CheckMulUB(T A, T B, T &R) {
+ static std::enable_if_t<std::is_unsigned<T>::value, bool> CheckMulUB(T A, T B,
+ T &R) {
R = A * B;
return false;
}
template <typename T, T Min, T Max>
- static typename std::enable_if<std::is_signed<T>::value, bool>::type
+ static std::enable_if_t<std::is_signed<T>::value, bool>
CheckRange(int64_t V) {
return Min <= V && V <= Max;
}
template <typename T, T Min, T Max>
- static typename std::enable_if<std::is_unsigned<T>::value, bool>::type
+ static std::enable_if_t<std::is_unsigned<T>::value, bool>
CheckRange(int64_t V) {
return V >= 0 && static_cast<uint64_t>(V) <= Max;
}
diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index 1a8109cedf769..cec3f6d6160ec 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -334,7 +334,7 @@ bool CheckCallable(InterpState &S, CodePtr OpPC, Function *F) {
const SourceLocation &Loc = S.Current->getLocation(OpPC);
if (F->isVirtual()) {
- if (!S.getLangOpts().CPlusPlus2a) {
+ if (!S.getLangOpts().CPlusPlus20) {
S.CCEDiag(Loc, diag::note_constexpr_virtual_call);
return false;
}
diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index c12caa639da71..a63c5a871ba33 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -869,7 +869,7 @@ inline bool ShiftRight(InterpState &S, CodePtr OpPC, const T &V, unsigned RHS) {
template <PrimType TL, PrimType TR, typename T = typename PrimConv<TL>::T>
inline bool ShiftLeft(InterpState &S, CodePtr OpPC, const T &V, unsigned RHS) {
- if (V.isSigned() && !S.getLangOpts().CPlusPlus2a) {
+ if (V.isSigned() && !S.getLangOpts().CPlusPlus20) {
// C++11 [expr.shift]p2: A signed left shift must have a non-negative
// operand, and must not overflow the corresponding unsigned type.
// C++2a [expr.shift]p2: E1 << E2 is the unique value congruent to
diff --git a/clang/lib/AST/Interp/Block.cpp b/clang/lib/AST/Interp/InterpBlock.cpp
index 5fc93eb39f4ea..ed6e8910194d8 100644
--- a/clang/lib/AST/Interp/Block.cpp
+++ b/clang/lib/AST/Interp/InterpBlock.cpp
@@ -10,7 +10,7 @@
//
//===----------------------------------------------------------------------===//
-#include "Block.h"
+#include "InterpBlock.h"
#include "Pointer.h"
using namespace clang;
diff --git a/clang/lib/AST/Interp/Block.h b/clang/lib/AST/Interp/InterpBlock.h
index 97fb9a3ca0961..0ccdef221c836 100644
--- a/clang/lib/AST/Interp/Block.h
+++ b/clang/lib/AST/Interp/InterpBlock.h
@@ -1,4 +1,4 @@
-//===--- Block.h - Allocated blocks for the interpreter ---------*- C++ -*-===//
+//===-- InterpBlock.h - Allocated blocks for the interpreter -*- C++ ----*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/lib/AST/Interp/InterpFrame.h b/clang/lib/AST/Interp/InterpFrame.h
index b8391b0bcf92c..304e2ad66537b 100644
--- a/clang/lib/AST/Interp/InterpFrame.h
+++ b/clang/lib/AST/Interp/InterpFrame.h
@@ -45,16 +45,16 @@ public:
void popArgs();
/// Describes the frame with arguments for diagnostic purposes.
- void describe(llvm::raw_ostream &OS);
+ void describe(llvm::raw_ostream &OS) override;
/// Returns the parent frame object.
- Frame *getCaller() const;
+ Frame *getCaller() const override;
/// Returns the location of the call to the frame.
- SourceLocation getCallLocation() const;
+ SourceLocation getCallLocation() const override;
/// Returns the caller.
- const FunctionDecl *getCallee() const;
+ const FunctionDecl *getCallee() const override;
/// Returns the current function.
Function *getFunction() const { return Func; }
diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp
index 1a10723aaca53..ef2638e2a36bd 100644
--- a/clang/lib/AST/Interp/Pointer.cpp
+++ b/clang/lib/AST/Interp/Pointer.cpp
@@ -7,8 +7,8 @@
//===----------------------------------------------------------------------===//
#include "Pointer.h"
-#include "Block.h"
#include "Function.h"
+#include "InterpBlock.h"
#include "PrimType.h"
using namespace clang;
diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h
index b8fa98e24faab..f2f6e0e760185 100644
--- a/clang/lib/AST/Interp/Pointer.h
+++ b/clang/lib/AST/Interp/Pointer.h
@@ -13,12 +13,12 @@
#ifndef LLVM_CLANG_AST_INTERP_POINTER_H
#define LLVM_CLANG_AST_INTERP_POINTER_H
-#include "Block.h"
#include "Descriptor.h"
+#include "InterpBlock.h"
+#include "clang/AST/ComparisonCategories.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
-#include "clang/AST/ComparisonCategories.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/clang/lib/AST/Interp/Source.h b/clang/lib/AST/Interp/Source.h
index e591c3399d7c1..19c652b7331a1 100644
--- a/clang/lib/AST/Interp/Source.h
+++ b/clang/lib/AST/Interp/Source.h
@@ -56,14 +56,14 @@ private:
/// Helper to decode a value or a pointer.
template <typename T>
- static typename std::enable_if<!std::is_pointer<T>::value, T>::type
+ static std::enable_if_t<!std::is_pointer<T>::value, T>
ReadHelper(const char *Ptr) {
using namespace llvm::support;
return endian::read<T, endianness::native, 1>(Ptr);
}
template <typename T>
- static typename std::enable_if<std::is_pointer<T>::value, T>::type
+ static std::enable_if_t<std::is_pointer<T>::value, T>
ReadHelper(const char *Ptr) {
using namespace llvm::support;
auto Punned = endian::read<uintptr_t, endianness::native, 1>(Ptr);
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 0d567edac5216..ddfbe9f864991 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -13,6 +13,7 @@
// http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling
//
//===----------------------------------------------------------------------===//
+
#include "clang/AST/Mangle.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
@@ -22,10 +23,12 @@
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprConcepts.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/ABI.h"
+#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/StringExtras.h"
@@ -124,8 +127,9 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext {
public:
explicit ItaniumMangleContextImpl(ASTContext &Context,
- DiagnosticsEngine &Diags)
- : ItaniumMangleContext(Context, Diags) {}
+ DiagnosticsEngine &Diags,
+ bool IsUniqueNameMangler)
+ : ItaniumMangleContext(Context, Diags, IsUniqueNameMangler) {}
/// @name Mangler Entry Points
/// @{
@@ -134,7 +138,7 @@ public:
bool shouldMangleStringLiteral(const StringLiteral *) override {
return false;
}
- void mangleCXXName(const NamedDecl *D, raw_ostream &) override;
+ void mangleCXXName(GlobalDecl GD, raw_ostream &) override;
void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk,
raw_ostream &) override;
void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
@@ -149,10 +153,6 @@ public:
void mangleCXXRTTI(QualType T, raw_ostream &) override;
void mangleCXXRTTIName(QualType T, raw_ostream &) override;
void mangleTypeName(QualType T, raw_ostream &) override;
- void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
- raw_ostream &) override;
- void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
- raw_ostream &) override;
void mangleCXXCtorComdat(const CXXConstructorDecl *D, raw_ostream &) override;
void mangleCXXDtorComdat(const CXXDestructorDecl *D, raw_ostream &) override;
@@ -160,6 +160,7 @@ public:
void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override;
void mangleDynamicAtExitDestructor(const VarDecl *D,
raw_ostream &Out) override;
+ void mangleDynamicStermFinalizer(const VarDecl *D, raw_ostream &Out) override;
void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
raw_ostream &Out) override;
void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
@@ -416,14 +417,14 @@ public:
void disableDerivedAbiTags() { DisableDerivedAbiTags = true; }
static bool shouldHaveAbiTags(ItaniumMangleContextImpl &C, const VarDecl *VD);
- void mangle(const NamedDecl *D);
+ void mangle(GlobalDecl GD);
void mangleCallOffset(int64_t NonVirtual, int64_t Virtual);
void mangleNumber(const llvm::APSInt &I);
void mangleNumber(int64_t Number);
void mangleFloat(const llvm::APFloat &F);
- void mangleFunctionEncoding(const FunctionDecl *FD);
+ void mangleFunctionEncoding(GlobalDecl GD);
void mangleSeqID(unsigned SeqID);
- void mangleName(const NamedDecl *ND);
+ void mangleName(GlobalDecl GD);
void mangleType(QualType T);
void mangleNameOrStandardSubstitution(const NamedDecl *ND);
void mangleLambdaSig(const CXXRecordDecl *Lambda);
@@ -460,38 +461,39 @@ private:
void mangleFunctionEncodingBareType(const FunctionDecl *FD);
- void mangleNameWithAbiTags(const NamedDecl *ND,
+ void mangleNameWithAbiTags(GlobalDecl GD,
const AbiTagList *AdditionalAbiTags);
void mangleModuleName(const Module *M);
void mangleModuleNamePrefix(StringRef Name);
void mangleTemplateName(const TemplateDecl *TD,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs);
- void mangleUnqualifiedName(const NamedDecl *ND,
+ void mangleUnqualifiedName(GlobalDecl GD,
const AbiTagList *AdditionalAbiTags) {
- mangleUnqualifiedName(ND, ND->getDeclName(), UnknownArity,
+ mangleUnqualifiedName(GD, cast<NamedDecl>(GD.getDecl())->getDeclName(), UnknownArity,
AdditionalAbiTags);
}
- void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name,
+ void mangleUnqualifiedName(GlobalDecl GD, DeclarationName Name,
unsigned KnownArity,
const AbiTagList *AdditionalAbiTags);
- void mangleUnscopedName(const NamedDecl *ND,
+ void mangleUnscopedName(GlobalDecl GD,
const AbiTagList *AdditionalAbiTags);
- void mangleUnscopedTemplateName(const TemplateDecl *ND,
+ void mangleUnscopedTemplateName(GlobalDecl GD,
const AbiTagList *AdditionalAbiTags);
void mangleUnscopedTemplateName(TemplateName,
const AbiTagList *AdditionalAbiTags);
void mangleSourceName(const IdentifierInfo *II);
void mangleRegCallName(const IdentifierInfo *II);
+ void mangleDeviceStubName(const IdentifierInfo *II);
void mangleSourceNameWithAbiTags(
const NamedDecl *ND, const AbiTagList *AdditionalAbiTags = nullptr);
- void mangleLocalName(const Decl *D,
+ void mangleLocalName(GlobalDecl GD,
const AbiTagList *AdditionalAbiTags);
void mangleBlockForPrefix(const BlockDecl *Block);
void mangleUnqualifiedBlock(const BlockDecl *Block);
void mangleTemplateParamDecl(const NamedDecl *Decl);
void mangleLambda(const CXXRecordDecl *Lambda);
- void mangleNestedName(const NamedDecl *ND, const DeclContext *DC,
+ void mangleNestedName(GlobalDecl GD, const DeclContext *DC,
const AbiTagList *AdditionalAbiTags,
bool NoFunction=false);
void mangleNestedName(const TemplateDecl *TD,
@@ -500,7 +502,7 @@ private:
void manglePrefix(NestedNameSpecifier *qualifier);
void manglePrefix(const DeclContext *DC, bool NoFunction=false);
void manglePrefix(QualType type);
- void mangleTemplatePrefix(const TemplateDecl *ND, bool NoFunction=false);
+ void mangleTemplatePrefix(GlobalDecl GD, bool NoFunction=false);
void mangleTemplatePrefix(TemplateName Template);
bool mangleUnresolvedTypeOrSimpleId(QualType DestroyedType,
StringRef Prefix = "");
@@ -639,34 +641,40 @@ void CXXNameMangler::mangleSourceNameWithAbiTags(
writeAbiTags(ND, AdditionalAbiTags);
}
-void CXXNameMangler::mangle(const NamedDecl *D) {
+void CXXNameMangler::mangle(GlobalDecl GD) {
// <mangled-name> ::= _Z <encoding>
// ::= <data name>
// ::= <special-name>
Out << "_Z";
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- mangleFunctionEncoding(FD);
- else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
+ if (isa<FunctionDecl>(GD.getDecl()))
+ mangleFunctionEncoding(GD);
+ else if (const VarDecl *VD = dyn_cast<VarDecl>(GD.getDecl()))
mangleName(VD);
- else if (const IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(D))
+ else if (const IndirectFieldDecl *IFD =
+ dyn_cast<IndirectFieldDecl>(GD.getDecl()))
mangleName(IFD->getAnonField());
+ else if (const FieldDecl *FD = dyn_cast<FieldDecl>(GD.getDecl()))
+ mangleName(FD);
+ else if (const MSGuidDecl *GuidD = dyn_cast<MSGuidDecl>(GD.getDecl()))
+ mangleName(GuidD);
else
- mangleName(cast<FieldDecl>(D));
+ llvm_unreachable("unexpected kind of global decl");
}
-void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
+void CXXNameMangler::mangleFunctionEncoding(GlobalDecl GD) {
+ const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
// <encoding> ::= <function name> <bare-function-type>
// Don't mangle in the type if this isn't a decl we should typically mangle.
if (!Context.shouldMangleDeclName(FD)) {
- mangleName(FD);
+ mangleName(GD);
return;
}
AbiTagList ReturnTypeAbiTags = makeFunctionReturnTypeTags(FD);
if (ReturnTypeAbiTags.empty()) {
// There are no tags for return type, the simplest case.
- mangleName(FD);
+ mangleName(GD);
mangleFunctionEncodingBareType(FD);
return;
}
@@ -786,13 +794,14 @@ static bool isStdNamespace(const DeclContext *DC) {
return isStd(cast<NamespaceDecl>(DC));
}
-static const TemplateDecl *
-isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) {
+static const GlobalDecl
+isTemplate(GlobalDecl GD, const TemplateArgumentList *&TemplateArgs) {
+ const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
// Check if we have a function template.
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
if (const TemplateDecl *TD = FD->getPrimaryTemplate()) {
TemplateArgs = FD->getTemplateSpecializationArgs();
- return TD;
+ return GD.getWithDecl(TD);
}
}
@@ -800,20 +809,21 @@ isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) {
if (const ClassTemplateSpecializationDecl *Spec =
dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
TemplateArgs = &Spec->getTemplateArgs();
- return Spec->getSpecializedTemplate();
+ return GD.getWithDecl(Spec->getSpecializedTemplate());
}
// Check if we have a variable template.
if (const VarTemplateSpecializationDecl *Spec =
dyn_cast<VarTemplateSpecializationDecl>(ND)) {
TemplateArgs = &Spec->getTemplateArgs();
- return Spec->getSpecializedTemplate();
+ return GD.getWithDecl(Spec->getSpecializedTemplate());
}
- return nullptr;
+ return GlobalDecl();
}
-void CXXNameMangler::mangleName(const NamedDecl *ND) {
+void CXXNameMangler::mangleName(GlobalDecl GD) {
+ const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
// Variables should have implicit tags from its type.
AbiTagList VariableTypeAbiTags = makeVariableTypeTags(VD);
@@ -842,12 +852,13 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) {
// Output name with implicit tags.
mangleNameWithAbiTags(VD, &AdditionalAbiTags);
} else {
- mangleNameWithAbiTags(ND, nullptr);
+ mangleNameWithAbiTags(GD, nullptr);
}
}
-void CXXNameMangler::mangleNameWithAbiTags(const NamedDecl *ND,
+void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD,
const AbiTagList *AdditionalAbiTags) {
+ const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
// <name> ::= [<module-name>] <nested-name>
// ::= [<module-name>] <unscoped-name>
// ::= [<module-name>] <unscoped-template-name> <template-args>
@@ -863,14 +874,14 @@ void CXXNameMangler::mangleNameWithAbiTags(const NamedDecl *ND,
while (!DC->isNamespace() && !DC->isTranslationUnit())
DC = getEffectiveParentContext(DC);
else if (GetLocalClassDecl(ND)) {
- mangleLocalName(ND, AdditionalAbiTags);
+ mangleLocalName(GD, AdditionalAbiTags);
return;
}
DC = IgnoreLinkageSpecDecls(DC);
if (isLocalContainerContext(DC)) {
- mangleLocalName(ND, AdditionalAbiTags);
+ mangleLocalName(GD, AdditionalAbiTags);
return;
}
@@ -885,17 +896,17 @@ void CXXNameMangler::mangleNameWithAbiTags(const NamedDecl *ND,
if (DC->isTranslationUnit() || isStdNamespace(DC)) {
// Check if we have a template.
const TemplateArgumentList *TemplateArgs = nullptr;
- if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
+ if (GlobalDecl TD = isTemplate(GD, TemplateArgs)) {
mangleUnscopedTemplateName(TD, AdditionalAbiTags);
mangleTemplateArgs(*TemplateArgs);
return;
}
- mangleUnscopedName(ND, AdditionalAbiTags);
+ mangleUnscopedName(GD, AdditionalAbiTags);
return;
}
- mangleNestedName(ND, DC, AdditionalAbiTags);
+ mangleNestedName(GD, DC, AdditionalAbiTags);
}
void CXXNameMangler::mangleModuleName(const Module *M) {
@@ -946,19 +957,21 @@ void CXXNameMangler::mangleTemplateName(const TemplateDecl *TD,
}
}
-void CXXNameMangler::mangleUnscopedName(const NamedDecl *ND,
+void CXXNameMangler::mangleUnscopedName(GlobalDecl GD,
const AbiTagList *AdditionalAbiTags) {
+ const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
// <unscoped-name> ::= <unqualified-name>
// ::= St <unqualified-name> # ::std::
if (isStdNamespace(IgnoreLinkageSpecDecls(getEffectiveDeclContext(ND))))
Out << "St";
- mangleUnqualifiedName(ND, AdditionalAbiTags);
+ mangleUnqualifiedName(GD, AdditionalAbiTags);
}
void CXXNameMangler::mangleUnscopedTemplateName(
- const TemplateDecl *ND, const AbiTagList *AdditionalAbiTags) {
+ GlobalDecl GD, const AbiTagList *AdditionalAbiTags) {
+ const TemplateDecl *ND = cast<TemplateDecl>(GD.getDecl());
// <unscoped-template-name> ::= <unscoped-name>
// ::= <substitution>
if (mangleSubstitution(ND))
@@ -970,9 +983,9 @@ void CXXNameMangler::mangleUnscopedTemplateName(
"template template param cannot have abi tags");
mangleTemplateParameter(TTP->getDepth(), TTP->getIndex());
} else if (isa<BuiltinTemplateDecl>(ND) || isa<ConceptDecl>(ND)) {
- mangleUnscopedName(ND, AdditionalAbiTags);
+ mangleUnscopedName(GD, AdditionalAbiTags);
} else {
- mangleUnscopedName(ND->getTemplatedDecl(), AdditionalAbiTags);
+ mangleUnscopedName(GD.getWithDecl(ND->getTemplatedDecl()), AdditionalAbiTags);
}
addSubstitution(ND);
@@ -1249,10 +1262,11 @@ void CXXNameMangler::mangleUnresolvedName(
mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
}
-void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
+void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
DeclarationName Name,
unsigned KnownArity,
const AbiTagList *AdditionalAbiTags) {
+ const NamedDecl *ND = cast_or_null<NamedDecl>(GD.getDecl());
unsigned Arity = KnownArity;
// <unqualified-name> ::= <operator-name>
// ::= <ctor-dtor-name>
@@ -1278,6 +1292,16 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
break;
}
+ if (auto *GD = dyn_cast<MSGuidDecl>(ND)) {
+ // We follow MSVC in mangling GUID declarations as if they were variables
+ // with a particular reserved name. Continue the pretense here.
+ SmallString<sizeof("_GUID_12345678_1234_1234_1234_1234567890ab")> GUID;
+ llvm::raw_svector_ostream GUIDOS(GUID);
+ Context.mangleMSGuidDecl(GD, GUIDOS);
+ Out << GUID.size() << GUID;
+ break;
+ }
+
if (II) {
// Match GCC's naming convention for internal linkage symbols, for
// symbols that are not actually visible outside of this TU. GCC
@@ -1302,7 +1326,12 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
bool IsRegCall = FD &&
FD->getType()->castAs<FunctionType>()->getCallConv() ==
clang::CC_X86RegCall;
- if (IsRegCall)
+ bool IsDeviceStub =
+ FD && FD->hasAttr<CUDAGlobalAttr>() &&
+ GD.getKernelReferenceKind() == KernelReferenceKind::Stub;
+ if (IsDeviceStub)
+ mangleDeviceStubName(II);
+ else if (IsRegCall)
mangleRegCallName(II);
else
mangleSourceName(II);
@@ -1380,7 +1409,8 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
// <lambda-sig> ::= <template-param-decl>* <parameter-type>+
// # Parameter types or 'v' for 'void'.
if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) {
- if (Record->isLambda() && Record->getLambdaManglingNumber()) {
+ if (Record->isLambda() && (Record->getLambdaManglingNumber() ||
+ Context.isUniqueNameMangler())) {
assert(!AdditionalAbiTags &&
"Lambda type cannot have additional abi tags");
mangleLambda(Record);
@@ -1491,6 +1521,14 @@ void CXXNameMangler::mangleRegCallName(const IdentifierInfo *II) {
<< II->getName();
}
+void CXXNameMangler::mangleDeviceStubName(const IdentifierInfo *II) {
+ // <source-name> ::= <positive length number> __device_stub__ <identifier>
+ // <number> ::= [n] <non-negative decimal integer>
+ // <identifier> ::= <unqualified source code identifier>
+ Out << II->getLength() + sizeof("__device_stub__") - 1 << "__device_stub__"
+ << II->getName();
+}
+
void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) {
// <source-name> ::= <positive length number> <identifier>
// <number> ::= [n] <non-negative decimal integer>
@@ -1498,10 +1536,11 @@ void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) {
Out << II->getLength() << II->getName();
}
-void CXXNameMangler::mangleNestedName(const NamedDecl *ND,
+void CXXNameMangler::mangleNestedName(GlobalDecl GD,
const DeclContext *DC,
const AbiTagList *AdditionalAbiTags,
bool NoFunction) {
+ const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
// <nested-name>
// ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
// ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix>
@@ -1519,13 +1558,13 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND,
// Check if we have a template.
const TemplateArgumentList *TemplateArgs = nullptr;
- if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
+ if (GlobalDecl TD = isTemplate(GD, TemplateArgs)) {
mangleTemplatePrefix(TD, NoFunction);
mangleTemplateArgs(*TemplateArgs);
}
else {
manglePrefix(DC, NoFunction);
- mangleUnqualifiedName(ND, AdditionalAbiTags);
+ mangleUnqualifiedName(GD, AdditionalAbiTags);
}
Out << 'E';
@@ -1543,8 +1582,24 @@ void CXXNameMangler::mangleNestedName(const TemplateDecl *TD,
Out << 'E';
}
-void CXXNameMangler::mangleLocalName(const Decl *D,
+static GlobalDecl getParentOfLocalEntity(const DeclContext *DC) {
+ GlobalDecl GD;
+ // The Itanium spec says:
+ // For entities in constructors and destructors, the mangling of the
+ // complete object constructor or destructor is used as the base function
+ // name, i.e. the C1 or D1 version.
+ if (auto *CD = dyn_cast<CXXConstructorDecl>(DC))
+ GD = GlobalDecl(CD, Ctor_Complete);
+ else if (auto *DD = dyn_cast<CXXDestructorDecl>(DC))
+ GD = GlobalDecl(DD, Dtor_Complete);
+ else
+ GD = GlobalDecl(cast<FunctionDecl>(DC));
+ return GD;
+}
+
+void CXXNameMangler::mangleLocalName(GlobalDecl GD,
const AbiTagList *AdditionalAbiTags) {
+ const Decl *D = GD.getDecl();
// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
// := Z <function encoding> E s [<discriminator>]
// <local-name> := Z <function encoding> E d [ <parameter number> ]
@@ -1564,7 +1619,7 @@ void CXXNameMangler::mangleLocalName(const Decl *D,
else if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC))
mangleBlockForPrefix(BD);
else
- mangleFunctionEncoding(cast<FunctionDecl>(DC));
+ mangleFunctionEncoding(getParentOfLocalEntity(DC));
// Implicit ABI tags (from namespace) are not available in the following
// entity; reset to actually emitted tags, which are available.
@@ -1607,7 +1662,7 @@ void CXXNameMangler::mangleLocalName(const Decl *D,
mangleUnqualifiedBlock(BD);
} else {
const NamedDecl *ND = cast<NamedDecl>(D);
- mangleNestedName(ND, getEffectiveDeclContext(ND), AdditionalAbiTags,
+ mangleNestedName(GD, getEffectiveDeclContext(ND), AdditionalAbiTags,
true /*NoFunction*/);
}
} else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
@@ -1628,7 +1683,7 @@ void CXXNameMangler::mangleLocalName(const Decl *D,
assert(!AdditionalAbiTags && "Block cannot have additional abi tags");
mangleUnqualifiedBlock(BD);
} else {
- mangleUnqualifiedName(cast<NamedDecl>(D), AdditionalAbiTags);
+ mangleUnqualifiedName(GD, AdditionalAbiTags);
}
if (const NamedDecl *ND = dyn_cast<NamedDecl>(RD ? RD : D)) {
@@ -1730,6 +1785,37 @@ void CXXNameMangler::mangleTemplateParamDecl(const NamedDecl *Decl) {
}
}
+// Handles the __builtin_unique_stable_name feature for lambdas. Instead of the
+// ordinal of the lambda in its mangling, this does line/column to uniquely and
+// reliably identify the lambda. Additionally, macro expansions are expressed
+// as well to prevent macros causing duplicates.
+static void mangleUniqueNameLambda(CXXNameMangler &Mangler, SourceManager &SM,
+ raw_ostream &Out,
+ const CXXRecordDecl *Lambda) {
+ SourceLocation Loc = Lambda->getLocation();
+
+ PresumedLoc PLoc = SM.getPresumedLoc(Loc);
+ Mangler.mangleNumber(PLoc.getLine());
+ Out << "_";
+ Mangler.mangleNumber(PLoc.getColumn());
+
+ while(Loc.isMacroID()) {
+ SourceLocation SLToPrint = Loc;
+ if (SM.isMacroArgExpansion(Loc))
+ SLToPrint = SM.getImmediateExpansionRange(Loc).getBegin();
+
+ PLoc = SM.getPresumedLoc(SM.getSpellingLoc(SLToPrint));
+ Out << "m";
+ Mangler.mangleNumber(PLoc.getLine());
+ Out << "_";
+ Mangler.mangleNumber(PLoc.getColumn());
+
+ Loc = SM.getImmediateMacroCallerLoc(Loc);
+ if (Loc.isFileID())
+ Loc = SM.getImmediateMacroCallerLoc(SLToPrint);
+ }
+}
+
void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
// If the context of a closure type is an initializer for a class member
// (static or nonstatic), it is encoded in a qualified name with a final
@@ -1760,6 +1846,12 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
mangleLambdaSig(Lambda);
Out << "E";
+ if (Context.isUniqueNameMangler()) {
+ mangleUniqueNameLambda(
+ *this, Context.getASTContext().getSourceManager(), Out, Lambda);
+ return;
+ }
+
// The number is omitted for the first closure type with a given
// <lambda-sig> in a given context; it is n-2 for the nth closure type
// (in lexical order) with that same <lambda-sig> and context.
@@ -1775,8 +1867,8 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
void CXXNameMangler::mangleLambdaSig(const CXXRecordDecl *Lambda) {
for (auto *D : Lambda->getLambdaExplicitTemplateParameters())
mangleTemplateParamDecl(D);
- const FunctionProtoType *Proto = Lambda->getLambdaTypeInfo()->getType()->
- getAs<FunctionProtoType>();
+ auto *Proto =
+ Lambda->getLambdaTypeInfo()->getType()->castAs<FunctionProtoType>();
mangleBareFunctionType(Proto, /*MangleReturnType=*/false,
Lambda->getLambdaStaticInvoker());
}
@@ -1839,7 +1931,7 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
// Check if we have a template.
const TemplateArgumentList *TemplateArgs = nullptr;
- if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
+ if (GlobalDecl TD = isTemplate(ND, TemplateArgs)) {
mangleTemplatePrefix(TD);
mangleTemplateArgs(*TemplateArgs);
} else {
@@ -1862,7 +1954,7 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) {
if (OverloadedTemplateStorage *Overloaded
= Template.getAsOverloadedTemplate()) {
- mangleUnqualifiedName(nullptr, (*Overloaded->begin())->getDeclName(),
+ mangleUnqualifiedName(GlobalDecl(), (*Overloaded->begin())->getDeclName(),
UnknownArity, nullptr);
return;
}
@@ -1874,8 +1966,9 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) {
mangleUnscopedTemplateName(Template, /* AdditionalAbiTags */ nullptr);
}
-void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND,
+void CXXNameMangler::mangleTemplatePrefix(GlobalDecl GD,
bool NoFunction) {
+ const TemplateDecl *ND = cast<TemplateDecl>(GD.getDecl());
// <template-prefix> ::= <prefix> <template unqualified-name>
// ::= <template-param>
// ::= <substitution>
@@ -1891,9 +1984,9 @@ void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND,
} else {
manglePrefix(getEffectiveDeclContext(ND), NoFunction);
if (isa<BuiltinTemplateDecl>(ND) || isa<ConceptDecl>(ND))
- mangleUnqualifiedName(ND, nullptr);
+ mangleUnqualifiedName(GD, nullptr);
else
- mangleUnqualifiedName(ND->getTemplatedDecl(), nullptr);
+ mangleUnqualifiedName(GD.getWithDecl(ND->getTemplatedDecl()), nullptr);
}
addSubstitution(ND);
@@ -1987,6 +2080,8 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
case Type::DependentSizedExtVector:
case Type::Vector:
case Type::ExtVector:
+ case Type::ConstantMatrix:
+ case Type::DependentSizedMatrix:
case Type::FunctionProto:
case Type::FunctionNoProto:
case Type::Paren:
@@ -2001,6 +2096,8 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
case Type::Atomic:
case Type::Pipe:
case Type::MacroQualified:
+ case Type::ExtInt:
+ case Type::DependentExtInt:
llvm_unreachable("type is illegal as a nested name specifier");
case Type::SubstTemplateTypeParmPack:
@@ -2668,6 +2765,11 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
Out << TI->getFloat128Mangling();
break;
}
+ case BuiltinType::BFloat16: {
+ const TargetInfo *TI = &getASTContext().getTargetInfo();
+ Out << TI->getBFloat16Mangling();
+ break;
+ }
case BuiltinType::NullPtr:
Out << "Dn";
break;
@@ -2719,10 +2821,18 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
// The SVE types are effectively target-specific. The mangling scheme
// is defined in the appendices to the Procedure Call Standard for the
// Arm Architecture.
-#define SVE_TYPE(Name, Id, SingletonId) \
- case BuiltinType::Id: \
- type_name = Name; \
- Out << 'u' << type_name.size() << type_name; \
+#define SVE_VECTOR_TYPE(InternalName, MangledName, Id, SingletonId, NumEls, \
+ ElBits, IsSigned, IsFP, IsBF) \
+ case BuiltinType::Id: \
+ type_name = MangledName; \
+ Out << (type_name == InternalName ? "u" : "") << type_name.size() \
+ << type_name; \
+ break;
+#define SVE_PREDICATE_TYPE(InternalName, MangledName, Id, SingletonId, NumEls) \
+ case BuiltinType::Id: \
+ type_name = MangledName; \
+ Out << (type_name == InternalName ? "u" : "") << type_name.size() \
+ << type_name; \
break;
#include "clang/Basic/AArch64SVEACLETypes.def"
}
@@ -3066,6 +3176,7 @@ void CXXNameMangler::mangleNeonVectorType(const VectorType *T) {
case BuiltinType::UShort:
EltName = "poly16_t";
break;
+ case BuiltinType::LongLong:
case BuiltinType::ULongLong:
EltName = "poly64_t";
break;
@@ -3083,7 +3194,8 @@ void CXXNameMangler::mangleNeonVectorType(const VectorType *T) {
case BuiltinType::ULongLong: EltName = "uint64_t"; break;
case BuiltinType::Double: EltName = "float64_t"; break;
case BuiltinType::Float: EltName = "float32_t"; break;
- case BuiltinType::Half: EltName = "float16_t";break;
+ case BuiltinType::Half: EltName = "float16_t"; break;
+ case BuiltinType::BFloat16: EltName = "bfloat16_t"; break;
default:
llvm_unreachable("unexpected Neon vector element type");
}
@@ -3135,6 +3247,8 @@ static StringRef mangleAArch64VectorBase(const BuiltinType *EltType) {
return "Float32";
case BuiltinType::Double:
return "Float64";
+ case BuiltinType::BFloat16:
+ return "BFloat16";
default:
llvm_unreachable("Unexpected vector element base type");
}
@@ -3249,6 +3363,31 @@ void CXXNameMangler::mangleType(const DependentSizedExtVectorType *T) {
mangleType(T->getElementType());
}
+void CXXNameMangler::mangleType(const ConstantMatrixType *T) {
+ // Mangle matrix types using a vendor extended type qualifier:
+ // U<Len>matrix_type<Rows><Columns><element type>
+ StringRef VendorQualifier = "matrix_type";
+ Out << "U" << VendorQualifier.size() << VendorQualifier;
+ auto &ASTCtx = getASTContext();
+ unsigned BitWidth = ASTCtx.getTypeSize(ASTCtx.getSizeType());
+ llvm::APSInt Rows(BitWidth);
+ Rows = T->getNumRows();
+ mangleIntegerLiteral(ASTCtx.getSizeType(), Rows);
+ llvm::APSInt Columns(BitWidth);
+ Columns = T->getNumColumns();
+ mangleIntegerLiteral(ASTCtx.getSizeType(), Columns);
+ mangleType(T->getElementType());
+}
+
+void CXXNameMangler::mangleType(const DependentSizedMatrixType *T) {
+ // U<Len>matrix_type<row expr><column expr><element type>
+ StringRef VendorQualifier = "matrix_type";
+ Out << "U" << VendorQualifier.size() << VendorQualifier;
+ mangleTemplateArg(T->getRowExpr());
+ mangleTemplateArg(T->getColumnExpr());
+ mangleType(T->getElementType());
+}
+
void CXXNameMangler::mangleType(const DependentAddressSpaceType *T) {
SplitQualType split = T->getPointeeType().split();
mangleQualifiers(split.Quals, T);
@@ -3459,6 +3598,28 @@ void CXXNameMangler::mangleType(const PipeType *T) {
Out << "8ocl_pipe";
}
+void CXXNameMangler::mangleType(const ExtIntType *T) {
+ Out << "U7_ExtInt";
+ llvm::APSInt BW(32, true);
+ BW = T->getNumBits();
+ TemplateArgument TA(Context.getASTContext(), BW, getASTContext().IntTy);
+ mangleTemplateArgs(&TA, 1);
+ if (T->isUnsigned())
+ Out << "j";
+ else
+ Out << "i";
+}
+
+void CXXNameMangler::mangleType(const DependentExtIntType *T) {
+ Out << "U7_ExtInt";
+ TemplateArgument TA(T->getNumBitsExpr());
+ mangleTemplateArgs(&TA, 1);
+ if (T->isUnsigned())
+ Out << "j";
+ else
+ Out << "i";
+}
+
void CXXNameMangler::mangleIntegerLiteral(QualType T,
const llvm::APSInt &Value) {
// <expr-primary> ::= L <type> <value number> E # integer literal
@@ -3633,8 +3794,11 @@ recurse:
case Expr::LambdaExprClass:
case Expr::MSPropertyRefExprClass:
case Expr::MSPropertySubscriptExprClass:
- case Expr::TypoExprClass: // This should no longer exist in the AST by now.
+ case Expr::TypoExprClass: // This should no longer exist in the AST by now.
+ case Expr::RecoveryExprClass:
case Expr::OMPArraySectionExprClass:
+ case Expr::OMPArrayShapingExprClass:
+ case Expr::OMPIteratorExprClass:
case Expr::CXXInheritedCtorInitExprClass:
llvm_unreachable("unexpected statement kind");
@@ -3668,6 +3832,7 @@ recurse:
case Expr::ConvertVectorExprClass:
case Expr::StmtExprClass:
case Expr::TypeTraitExprClass:
+ case Expr::RequiresExprClass:
case Expr::ArrayTypeTraitExprClass:
case Expr::ExpressionTraitExprClass:
case Expr::VAArgExprClass:
@@ -4087,6 +4252,15 @@ recurse:
break;
}
+ case Expr::MatrixSubscriptExprClass: {
+ const MatrixSubscriptExpr *ME = cast<MatrixSubscriptExpr>(E);
+ Out << "ixix";
+ mangleExpression(ME->getBase());
+ mangleExpression(ME->getRowIdx());
+ mangleExpression(ME->getColumnIdx());
+ break;
+ }
+
case Expr::CompoundAssignOperatorClass: // fallthrough
case Expr::BinaryOperatorClass: {
const BinaryOperator *BO = cast<BinaryOperator>(E);
@@ -4170,6 +4344,9 @@ recurse:
case Expr::CXXConstCastExprClass:
mangleCastExpression(E, "cc");
break;
+ case Expr::CXXAddrspaceCastExprClass:
+ mangleCastExpression(E, "ac");
+ break;
case Expr::CXXOperatorCallExprClass: {
const CXXOperatorCallExpr *CE = cast<CXXOperatorCallExpr>(E);
@@ -4941,45 +5118,42 @@ bool CXXNameMangler::shouldHaveAbiTags(ItaniumMangleContextImpl &C,
/// and this routine will return false. In this case, the caller should just
/// emit the identifier of the declaration (\c D->getIdentifier()) as its
/// name.
-void ItaniumMangleContextImpl::mangleCXXName(const NamedDecl *D,
+void ItaniumMangleContextImpl::mangleCXXName(GlobalDecl GD,
raw_ostream &Out) {
+ const NamedDecl *D = cast<NamedDecl>(GD.getDecl());
assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
"Invalid mangleName() call, argument is not a variable or function!");
- assert(!isa<CXXConstructorDecl>(D) && !isa<CXXDestructorDecl>(D) &&
- "Invalid mangleName() call on 'structor decl!");
PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
getASTContext().getSourceManager(),
"Mangling declaration");
- CXXNameMangler Mangler(*this, Out, D);
- Mangler.mangle(D);
-}
+ if (auto *CD = dyn_cast<CXXConstructorDecl>(D)) {
+ auto Type = GD.getCtorType();
+ CXXNameMangler Mangler(*this, Out, CD, Type);
+ return Mangler.mangle(GlobalDecl(CD, Type));
+ }
-void ItaniumMangleContextImpl::mangleCXXCtor(const CXXConstructorDecl *D,
- CXXCtorType Type,
- raw_ostream &Out) {
- CXXNameMangler Mangler(*this, Out, D, Type);
- Mangler.mangle(D);
-}
+ if (auto *DD = dyn_cast<CXXDestructorDecl>(D)) {
+ auto Type = GD.getDtorType();
+ CXXNameMangler Mangler(*this, Out, DD, Type);
+ return Mangler.mangle(GlobalDecl(DD, Type));
+ }
-void ItaniumMangleContextImpl::mangleCXXDtor(const CXXDestructorDecl *D,
- CXXDtorType Type,
- raw_ostream &Out) {
- CXXNameMangler Mangler(*this, Out, D, Type);
- Mangler.mangle(D);
+ CXXNameMangler Mangler(*this, Out, D);
+ Mangler.mangle(GD);
}
void ItaniumMangleContextImpl::mangleCXXCtorComdat(const CXXConstructorDecl *D,
raw_ostream &Out) {
CXXNameMangler Mangler(*this, Out, D, Ctor_Comdat);
- Mangler.mangle(D);
+ Mangler.mangle(GlobalDecl(D, Ctor_Comdat));
}
void ItaniumMangleContextImpl::mangleCXXDtorComdat(const CXXDestructorDecl *D,
raw_ostream &Out) {
CXXNameMangler Mangler(*this, Out, D, Dtor_Comdat);
- Mangler.mangle(D);
+ Mangler.mangle(GlobalDecl(D, Dtor_Comdat));
}
void ItaniumMangleContextImpl::mangleThunk(const CXXMethodDecl *MD,
@@ -5023,7 +5197,7 @@ void ItaniumMangleContextImpl::mangleCXXDtorThunk(
Mangler.mangleCallOffset(ThisAdjustment.NonVirtual,
ThisAdjustment.Virtual.Itanium.VCallOffsetOffset);
- Mangler.mangleFunctionEncoding(DD);
+ Mangler.mangleFunctionEncoding(GlobalDecl(DD, Type));
}
/// Returns the mangled name for a guard variable for the passed in VarDecl.
@@ -5057,6 +5231,18 @@ void ItaniumMangleContextImpl::mangleDynamicAtExitDestructor(const VarDecl *D,
Mangler.getStream() << D->getName();
}
+void ItaniumMangleContextImpl::mangleDynamicStermFinalizer(const VarDecl *D,
+ raw_ostream &Out) {
+ // Clang generates these internal-linkage functions as part of its
+ // implementation of the XL ABI.
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "__finalize_";
+ if (shouldMangleDeclName(D))
+ Mangler.mangle(D);
+ else
+ Mangler.getStream() << D->getName();
+}
+
void ItaniumMangleContextImpl::mangleSEHFilterExpression(
const NamedDecl *EnclosingDecl, raw_ostream &Out) {
CXXNameMangler Mangler(*this, Out);
@@ -5165,7 +5351,8 @@ void ItaniumMangleContextImpl::mangleLambdaSig(const CXXRecordDecl *Lambda,
Mangler.mangleLambdaSig(Lambda);
}
-ItaniumMangleContext *
-ItaniumMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) {
- return new ItaniumMangleContextImpl(Context, Diags);
+ItaniumMangleContext *ItaniumMangleContext::create(ASTContext &Context,
+ DiagnosticsEngine &Diags,
+ bool IsUniqueNameMangler) {
+ return new ItaniumMangleContextImpl(Context, Diags, IsUniqueNameMangler);
}
diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp
index c30b07137edcf..4bd00ece86ab8 100644
--- a/clang/lib/AST/JSONNodeDumper.cpp
+++ b/clang/lib/AST/JSONNodeDumper.cpp
@@ -1,4 +1,6 @@
#include "clang/AST/JSONNodeDumper.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Specifiers.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/StringSwitch.h"
@@ -72,6 +74,7 @@ void JSONNodeDumper::Visit(const Type *T) {
JOS.attribute("kind", (llvm::Twine(T->getTypeClassName()) + "Type").str());
JOS.attribute("type", createQualType(QualType(T, 0), /*Desugar*/ false));
+ attributeOnlyIfTrue("containsErrors", T->containsErrors());
attributeOnlyIfTrue("isDependent", T->isDependentType());
attributeOnlyIfTrue("isInstantiationDependent",
T->isInstantiationDependentType());
@@ -109,7 +112,7 @@ void JSONNodeDumper::Visit(const Decl *D) {
JOS.attribute("isReferenced", true);
if (const auto *ND = dyn_cast<NamedDecl>(D))
- attributeOnlyIfTrue("isHidden", ND->isHidden());
+ attributeOnlyIfTrue("isHidden", !ND->isUnconditionallyVisible());
if (D->getLexicalDeclContext() != D->getDeclContext()) {
// Because of multiple inheritance, a DeclContext pointer does not produce
@@ -180,6 +183,13 @@ void JSONNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) {
attributeOnlyIfTrue("selected", A.isSelected());
}
+void JSONNodeDumper::Visit(const APValue &Value, QualType Ty) {
+ std::string Str;
+ llvm::raw_string_ostream OS(Str);
+ Value.printPretty(OS, Ctx, Ty);
+ JOS.attribute("value", OS.str());
+}
+
void JSONNodeDumper::writeIncludeStack(PresumedLoc Loc, bool JustFirst) {
if (Loc.isInvalid())
return;
@@ -384,6 +394,7 @@ static llvm::json::Object
createCopyAssignmentDefinitionData(const CXXRecordDecl *RD) {
llvm::json::Object Ret;
+ FIELD2("simple", hasSimpleCopyAssignment);
FIELD2("trivial", hasTrivialCopyAssignment);
FIELD2("nonTrivial", hasNonTrivialCopyAssignment);
FIELD2("hasConstParam", hasCopyAssignmentWithConstParam);
@@ -464,13 +475,10 @@ JSONNodeDumper::createCXXRecordDefinitionData(const CXXRecordDecl *RD) {
#undef FIELD2
std::string JSONNodeDumper::createAccessSpecifier(AccessSpecifier AS) {
- switch (AS) {
- case AS_none: return "none";
- case AS_private: return "private";
- case AS_protected: return "protected";
- case AS_public: return "public";
- }
- llvm_unreachable("Unknown access specifier");
+ const auto AccessSpelling = getAccessSpelling(AS);
+ if (AccessSpelling.empty())
+ return "none";
+ return AccessSpelling.str();
}
llvm::json::Object
@@ -997,32 +1005,33 @@ void JSONNodeDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
case ObjCPropertyDecl::Required: JOS.attribute("control", "required"); break;
case ObjCPropertyDecl::Optional: JOS.attribute("control", "optional"); break;
}
-
- ObjCPropertyDecl::PropertyAttributeKind Attrs = D->getPropertyAttributes();
- if (Attrs != ObjCPropertyDecl::OBJC_PR_noattr) {
- if (Attrs & ObjCPropertyDecl::OBJC_PR_getter)
+
+ ObjCPropertyAttribute::Kind Attrs = D->getPropertyAttributes();
+ if (Attrs != ObjCPropertyAttribute::kind_noattr) {
+ if (Attrs & ObjCPropertyAttribute::kind_getter)
JOS.attribute("getter", createBareDeclRef(D->getGetterMethodDecl()));
- if (Attrs & ObjCPropertyDecl::OBJC_PR_setter)
+ if (Attrs & ObjCPropertyAttribute::kind_setter)
JOS.attribute("setter", createBareDeclRef(D->getSetterMethodDecl()));
- attributeOnlyIfTrue("readonly", Attrs & ObjCPropertyDecl::OBJC_PR_readonly);
- attributeOnlyIfTrue("assign", Attrs & ObjCPropertyDecl::OBJC_PR_assign);
+ attributeOnlyIfTrue("readonly",
+ Attrs & ObjCPropertyAttribute::kind_readonly);
+ attributeOnlyIfTrue("assign", Attrs & ObjCPropertyAttribute::kind_assign);
attributeOnlyIfTrue("readwrite",
- Attrs & ObjCPropertyDecl::OBJC_PR_readwrite);
- attributeOnlyIfTrue("retain", Attrs & ObjCPropertyDecl::OBJC_PR_retain);
- attributeOnlyIfTrue("copy", Attrs & ObjCPropertyDecl::OBJC_PR_copy);
+ Attrs & ObjCPropertyAttribute::kind_readwrite);
+ attributeOnlyIfTrue("retain", Attrs & ObjCPropertyAttribute::kind_retain);
+ attributeOnlyIfTrue("copy", Attrs & ObjCPropertyAttribute::kind_copy);
attributeOnlyIfTrue("nonatomic",
- Attrs & ObjCPropertyDecl::OBJC_PR_nonatomic);
- attributeOnlyIfTrue("atomic", Attrs & ObjCPropertyDecl::OBJC_PR_atomic);
- attributeOnlyIfTrue("weak", Attrs & ObjCPropertyDecl::OBJC_PR_weak);
- attributeOnlyIfTrue("strong", Attrs & ObjCPropertyDecl::OBJC_PR_strong);
+ Attrs & ObjCPropertyAttribute::kind_nonatomic);
+ attributeOnlyIfTrue("atomic", Attrs & ObjCPropertyAttribute::kind_atomic);
+ attributeOnlyIfTrue("weak", Attrs & ObjCPropertyAttribute::kind_weak);
+ attributeOnlyIfTrue("strong", Attrs & ObjCPropertyAttribute::kind_strong);
attributeOnlyIfTrue("unsafe_unretained",
- Attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
- attributeOnlyIfTrue("class", Attrs & ObjCPropertyDecl::OBJC_PR_class);
- attributeOnlyIfTrue("direct", Attrs & ObjCPropertyDecl::OBJC_PR_direct);
+ Attrs & ObjCPropertyAttribute::kind_unsafe_unretained);
+ attributeOnlyIfTrue("class", Attrs & ObjCPropertyAttribute::kind_class);
+ attributeOnlyIfTrue("direct", Attrs & ObjCPropertyAttribute::kind_direct);
attributeOnlyIfTrue("nullability",
- Attrs & ObjCPropertyDecl::OBJC_PR_nullability);
+ Attrs & ObjCPropertyAttribute::kind_nullability);
attributeOnlyIfTrue("null_resettable",
- Attrs & ObjCPropertyDecl::OBJC_PR_null_resettable);
+ Attrs & ObjCPropertyAttribute::kind_null_resettable);
}
}
@@ -1234,14 +1243,7 @@ void JSONNodeDumper::VisitCallExpr(const CallExpr *CE) {
void JSONNodeDumper::VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *TTE) {
- switch (TTE->getKind()) {
- case UETT_SizeOf: JOS.attribute("name", "sizeof"); break;
- case UETT_AlignOf: JOS.attribute("name", "alignof"); break;
- case UETT_VecStep: JOS.attribute("name", "vec_step"); break;
- case UETT_PreferredAlignOf: JOS.attribute("name", "__alignof"); break;
- case UETT_OpenMPRequiredSimdAlign:
- JOS.attribute("name", "__builtin_omp_required_simd_align"); break;
- }
+ JOS.attribute("name", getTraitSpelling(TTE->getKind()));
if (TTE->isArgumentType())
JOS.attribute("argType", createQualType(TTE->getArgumentType()));
}
@@ -1277,12 +1279,8 @@ void JSONNodeDumper::VisitCXXTypeidExpr(const CXXTypeidExpr *CTE) {
}
void JSONNodeDumper::VisitConstantExpr(const ConstantExpr *CE) {
- if (CE->getResultAPValueKind() != APValue::None) {
- std::string Str;
- llvm::raw_string_ostream OS(Str);
- CE->getAPValueResult().printPretty(OS, Ctx, CE->getType());
- JOS.attribute("value", OS.str());
- }
+ if (CE->getResultAPValueKind() != APValue::None)
+ Visit(CE->getAPValueResult(), CE->getType());
}
void JSONNodeDumper::VisitInitListExpr(const InitListExpr *ILE) {
@@ -1333,7 +1331,16 @@ void JSONNodeDumper::VisitExprWithCleanups(const ExprWithCleanups *EWC) {
if (EWC->getNumObjects()) {
JOS.attributeArray("cleanups", [this, EWC] {
for (const ExprWithCleanups::CleanupObject &CO : EWC->getObjects())
- JOS.value(createBareDeclRef(CO));
+ if (auto *BD = CO.dyn_cast<BlockDecl *>()) {
+ JOS.value(createBareDeclRef(BD));
+ } else if (auto *CLE = CO.dyn_cast<CompoundLiteralExpr *>()) {
+ llvm::json::Object Obj;
+ Obj["id"] = createPointerRepresentation(CLE);
+ Obj["kind"] = CLE->getStmtClassName();
+ JOS.value(std::move(Obj));
+ } else {
+ llvm_unreachable("unexpected cleanup object type");
+ }
});
}
}
diff --git a/clang/lib/AST/Linkage.h b/clang/lib/AST/Linkage.h
index 4e913540de86f..5d8acf0016f49 100644
--- a/clang/lib/AST/Linkage.h
+++ b/clang/lib/AST/Linkage.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_LIB_AST_LINKAGE_H
#define LLVM_CLANG_LIB_AST_LINKAGE_H
+#include "clang/AST/ASTFwd.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Type.h"
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index e106b31f59f02..a732325006c66 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -25,6 +25,7 @@
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Mangler.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -50,19 +51,32 @@ enum CCMangling {
CCM_Fast,
CCM_RegCall,
CCM_Vector,
- CCM_Std
+ CCM_Std,
+ CCM_WasmMainArgcArgv
};
static bool isExternC(const NamedDecl *ND) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
return FD->isExternC();
- return cast<VarDecl>(ND)->isExternC();
+ if (const VarDecl *VD = dyn_cast<VarDecl>(ND))
+ return VD->isExternC();
+ return false;
}
static CCMangling getCallingConvMangling(const ASTContext &Context,
const NamedDecl *ND) {
const TargetInfo &TI = Context.getTargetInfo();
const llvm::Triple &Triple = TI.getTriple();
+
+ // On wasm, the argc/argv form of "main" is renamed so that the startup code
+ // can call it with the correct function signature.
+ // On Emscripten, users may be exporting "main" and expecting to call it
+ // themselves, so we can't mangle it.
+ if (Triple.isWasm() && !Triple.isOSEmscripten())
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
+ if (FD->isMain() && FD->hasPrototype() && FD->param_size() == 2)
+ return CCM_WasmMainArgcArgv;
+
if (!Triple.isOSWindows() || !Triple.isX86())
return CCM_Other;
@@ -111,10 +125,15 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {
if (D->hasAttr<AsmLabelAttr>())
return true;
+ // Declarations that don't have identifier names always need to be mangled.
+ if (isa<MSGuidDecl>(D))
+ return true;
+
return shouldMangleCXXName(D);
}
-void MangleContext::mangleName(const NamedDecl *D, raw_ostream &Out) {
+void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
+ const NamedDecl *D = cast<NamedDecl>(GD.getDecl());
// Any decl can be declared with __asm("foo") on it, and this takes precedence
// over all other naming in the .o file.
if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
@@ -141,15 +160,24 @@ void MangleContext::mangleName(const NamedDecl *D, raw_ostream &Out) {
return;
}
+ if (auto *GD = dyn_cast<MSGuidDecl>(D))
+ return mangleMSGuidDecl(GD, Out);
+
const ASTContext &ASTContext = getASTContext();
CCMangling CC = getCallingConvMangling(ASTContext, D);
+
+ if (CC == CCM_WasmMainArgcArgv) {
+ Out << "__main_argc_argv";
+ return;
+ }
+
bool MCXX = shouldMangleCXXName(D);
const TargetInfo &TI = Context.getTargetInfo();
if (CC == CCM_Other || (MCXX && TI.getCXXABI() == TargetCXXABI::Microsoft)) {
if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))
mangleObjCMethodName(OMD, Out);
else
- mangleCXXName(D, Out);
+ mangleCXXName(GD, Out);
return;
}
@@ -166,7 +194,7 @@ void MangleContext::mangleName(const NamedDecl *D, raw_ostream &Out) {
else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))
mangleObjCMethodName(OMD, Out);
else
- mangleCXXName(D, Out);
+ mangleCXXName(GD, Out);
const FunctionDecl *FD = cast<FunctionDecl>(D);
const FunctionType *FT = FD->getType()->castAs<FunctionType>();
@@ -191,6 +219,20 @@ void MangleContext::mangleName(const NamedDecl *D, raw_ostream &Out) {
Out << ((TI.getPointerWidth(0) / 8) * ArgWords);
}
+void MangleContext::mangleMSGuidDecl(const MSGuidDecl *GD, raw_ostream &Out) {
+ // For now, follow the MSVC naming convention for GUID objects on all
+ // targets.
+ MSGuidDecl::Parts P = GD->getParts();
+ Out << llvm::format("_GUID_%08" PRIx32 "_%04" PRIx32 "_%04" PRIx32 "_",
+ P.Part1, P.Part2, P.Part3);
+ unsigned I = 0;
+ for (uint8_t C : P.Part4And5) {
+ Out << llvm::format("%02" PRIx8, C);
+ if (++I == 2)
+ Out << "_";
+ }
+}
+
void MangleContext::mangleGlobalBlock(const BlockDecl *BD,
const NamedDecl *ID,
raw_ostream &Out) {
@@ -213,7 +255,7 @@ void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD,
raw_ostream &ResStream) {
SmallString<64> Buffer;
llvm::raw_svector_ostream Out(Buffer);
- mangleCXXCtor(CD, CT, Out);
+ mangleName(GlobalDecl(CD, CT), Out);
mangleFunctionBlock(*this, Buffer, BD, ResStream);
}
@@ -222,7 +264,7 @@ void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD,
raw_ostream &ResStream) {
SmallString<64> Buffer;
llvm::raw_svector_ostream Out(Buffer);
- mangleCXXDtor(DD, DT, Out);
+ mangleName(GlobalDecl(DD, DT), Out);
mangleFunctionBlock(*this, Buffer, BD, ResStream);
}
@@ -358,7 +400,7 @@ public:
SmallString<40> Mangled;
auto Prefix = getClassSymbolPrefix(Kind, OCD->getASTContext());
llvm::Mangler::getNameWithPrefix(Mangled, Prefix + ClassName, DL);
- return Mangled.str();
+ return std::string(Mangled.str());
};
return {
@@ -420,12 +462,16 @@ public:
private:
bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) {
if (MC->shouldMangleDeclName(D)) {
+ GlobalDecl GD;
if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(D))
- MC->mangleCXXCtor(CtorD, Ctor_Complete, OS);
+ GD = GlobalDecl(CtorD, Ctor_Complete);
else if (const auto *DtorD = dyn_cast<CXXDestructorDecl>(D))
- MC->mangleCXXDtor(DtorD, Dtor_Complete, OS);
+ GD = GlobalDecl(DtorD, Dtor_Complete);
+ else if (D->hasAttr<CUDAGlobalAttr>())
+ GD = GlobalDecl(cast<FunctionDecl>(D));
else
- MC->mangleName(D, OS);
+ GD = GlobalDecl(D);
+ MC->mangleName(GD, OS);
return false;
} else {
IdentifierInfo *II = D->getIdentifier();
@@ -445,10 +491,12 @@ private:
std::string FrontendBuf;
llvm::raw_string_ostream FOS(FrontendBuf);
+ GlobalDecl GD;
if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND))
- MC->mangleCXXCtor(CD, static_cast<CXXCtorType>(StructorType), FOS);
+ GD = GlobalDecl(CD, static_cast<CXXCtorType>(StructorType));
else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND))
- MC->mangleCXXDtor(DD, static_cast<CXXDtorType>(StructorType), FOS);
+ GD = GlobalDecl(DD, static_cast<CXXDtorType>(StructorType));
+ MC->mangleName(GD, FOS);
std::string BackendBuf;
llvm::raw_string_ostream BOS(BackendBuf);
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index a286c53355840..529f301e46964 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -10,7 +10,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/Mangle.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/CXXInheritance.h"
@@ -22,9 +21,12 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/Mangle.h"
#include "clang/AST/VTableBuilder.h"
#include "clang/Basic/ABI.h"
#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CRC.h"
@@ -135,7 +137,7 @@ public:
MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags);
bool shouldMangleCXXName(const NamedDecl *D) override;
bool shouldMangleStringLiteral(const StringLiteral *SL) override;
- void mangleCXXName(const NamedDecl *D, raw_ostream &Out) override;
+ void mangleCXXName(GlobalDecl GD, raw_ostream &Out) override;
void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
const MethodVFTableLocation &ML,
raw_ostream &Out) override;
@@ -177,10 +179,6 @@ public:
ArrayRef<const CXXRecordDecl *> BasePath,
raw_ostream &Out) override;
void mangleTypeName(QualType T, raw_ostream &) override;
- void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
- raw_ostream &) override;
- void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
- raw_ostream &) override;
void mangleReferenceTemporary(const VarDecl *, unsigned ManglingNumber,
raw_ostream &) override;
void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out) override;
@@ -464,7 +462,7 @@ bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
if (VD->isExternC())
return false;
- // Variables at global scope with non-internal linkage are not mangled.
+ // Variables at global scope with internal linkage are not mangled.
const DeclContext *DC = getEffectiveDeclContext(D);
// Check for extern variable declared locally.
if (DC->isFunctionOrMethod() && D->hasLinkage())
@@ -499,6 +497,10 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) {
mangleFunctionEncoding(FD, Context.shouldMangleDeclName(FD));
else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
mangleVariableEncoding(VD);
+ else if (isa<MSGuidDecl>(D))
+ // MSVC appears to mangle GUIDs as if they were variables of type
+ // 'const struct __s_GUID'.
+ Out << "3U__s_GUID@@B";
else
llvm_unreachable("Tried to mangle unexpected NamedDecl!");
}
@@ -895,6 +897,16 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
break;
}
+ if (const MSGuidDecl *GD = dyn_cast<MSGuidDecl>(ND)) {
+ // Mangle a GUID object as if it were a variable with the corresponding
+ // mangled name.
+ SmallString<sizeof("_GUID_12345678_1234_1234_1234_1234567890ab")> GUID;
+ llvm::raw_svector_ostream GUIDOS(GUID);
+ Context.mangleMSGuidDecl(GD, GUIDOS);
+ mangleSourceName(GUID);
+ break;
+ }
+
// We must have an anonymous struct.
const TagDecl *TD = cast<TagDecl>(ND);
if (const TypedefNameDecl *D = TD->getTypedefNameForAnonDecl()) {
@@ -935,12 +947,12 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
mangleSourceName(Name);
- // If the context of a closure type is an initializer for a class
- // member (static or nonstatic), it is encoded in a qualified name.
+ // If the context is a variable or a class member and not a parameter,
+ // it is encoded in a qualified name.
if (LambdaManglingNumber && LambdaContextDecl) {
if ((isa<VarDecl>(LambdaContextDecl) ||
isa<FieldDecl>(LambdaContextDecl)) &&
- LambdaContextDecl->getDeclContext()->isRecord()) {
+ !isa<ParmVarDecl>(LambdaContextDecl)) {
mangleUnqualifiedName(cast<NamedDecl>(LambdaContextDecl));
}
}
@@ -1301,7 +1313,7 @@ void MicrosoftCXXNameMangler::mangleSourceName(StringRef Name) {
BackRefVec::iterator Found = llvm::find(NameBackReferences, Name);
if (Found == NameBackReferences.end()) {
if (NameBackReferences.size() < 10)
- NameBackReferences.push_back(Name);
+ NameBackReferences.push_back(std::string(Name));
Out << Name << '@';
} else {
Out << (Found - NameBackReferences.begin());
@@ -1366,45 +1378,6 @@ void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) {
return;
}
- // Look through no-op casts like template parameter substitutions.
- E = E->IgnoreParenNoopCasts(Context.getASTContext());
-
- const CXXUuidofExpr *UE = nullptr;
- if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
- if (UO->getOpcode() == UO_AddrOf)
- UE = dyn_cast<CXXUuidofExpr>(UO->getSubExpr());
- } else
- UE = dyn_cast<CXXUuidofExpr>(E);
-
- if (UE) {
- // If we had to peek through an address-of operator, treat this like we are
- // dealing with a pointer type. Otherwise, treat it like a const reference.
- //
- // N.B. This matches up with the handling of TemplateArgument::Declaration
- // in mangleTemplateArg
- if (UE == E)
- Out << "$E?";
- else
- Out << "$1?";
-
- // This CXXUuidofExpr is mangled as-if it were actually a VarDecl from
- // const __s_GUID _GUID_{lower case UUID with underscores}
- StringRef Uuid = UE->getUuidStr();
- std::string Name = "_GUID_" + Uuid.lower();
- std::replace(Name.begin(), Name.end(), '-', '_');
-
- mangleSourceName(Name);
- // Terminate the whole name with an '@'.
- Out << '@';
- // It's a global variable.
- Out << '3';
- // It's a struct called __s_GUID.
- mangleArtificialTagType(TTK_Struct, "__s_GUID");
- // It's const.
- Out << 'B';
- return;
- }
-
// As bad as this diagnostic is, it's better than crashing.
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
@@ -2141,6 +2114,7 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
case BuiltinType::SatUShortFract:
case BuiltinType::SatUFract:
case BuiltinType::SatULongFract:
+ case BuiltinType::BFloat16:
case BuiltinType::Float128: {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
@@ -2757,6 +2731,23 @@ void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T,
<< Range;
}
+void MicrosoftCXXNameMangler::mangleType(const ConstantMatrixType *T,
+ Qualifiers quals, SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "Cannot mangle this matrix type yet");
+ Diags.Report(Range.getBegin(), DiagID) << Range;
+}
+
+void MicrosoftCXXNameMangler::mangleType(const DependentSizedMatrixType *T,
+ Qualifiers quals, SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "Cannot mangle this dependent-sized matrix type yet");
+ Diags.Report(Range.getBegin(), DiagID) << Range;
+}
+
void MicrosoftCXXNameMangler::mangleType(const DependentAddressSpaceType *T,
Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
@@ -2942,29 +2933,68 @@ void MicrosoftCXXNameMangler::mangleType(const AtomicType *T, Qualifiers,
void MicrosoftCXXNameMangler::mangleType(const PipeType *T, Qualifiers,
SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this OpenCL pipe type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
+ QualType ElementType = T->getElementType();
+
+ llvm::SmallString<64> TemplateMangling;
+ llvm::raw_svector_ostream Stream(TemplateMangling);
+ MicrosoftCXXNameMangler Extra(Context, Stream);
+ Stream << "?$";
+ Extra.mangleSourceName("ocl_pipe");
+ Extra.mangleType(ElementType, Range, QMM_Escape);
+ Extra.mangleIntegerLiteral(llvm::APSInt::get(T->isReadOnly()), true);
+
+ mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__clang"});
}
-void MicrosoftMangleContextImpl::mangleCXXName(const NamedDecl *D,
+void MicrosoftMangleContextImpl::mangleCXXName(GlobalDecl GD,
raw_ostream &Out) {
- assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
- "Invalid mangleName() call, argument is not a variable or function!");
- assert(!isa<CXXConstructorDecl>(D) && !isa<CXXDestructorDecl>(D) &&
- "Invalid mangleName() call on 'structor decl!");
-
+ const NamedDecl *D = cast<NamedDecl>(GD.getDecl());
PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
getASTContext().getSourceManager(),
"Mangling declaration");
msvc_hashing_ostream MHO(Out);
+
+ if (auto *CD = dyn_cast<CXXConstructorDecl>(D)) {
+ auto Type = GD.getCtorType();
+ MicrosoftCXXNameMangler mangler(*this, MHO, CD, Type);
+ return mangler.mangle(D);
+ }
+
+ if (auto *DD = dyn_cast<CXXDestructorDecl>(D)) {
+ auto Type = GD.getDtorType();
+ MicrosoftCXXNameMangler mangler(*this, MHO, DD, Type);
+ return mangler.mangle(D);
+ }
+
MicrosoftCXXNameMangler Mangler(*this, MHO);
return Mangler.mangle(D);
}
+void MicrosoftCXXNameMangler::mangleType(const ExtIntType *T, Qualifiers,
+ SourceRange Range) {
+ llvm::SmallString<64> TemplateMangling;
+ llvm::raw_svector_ostream Stream(TemplateMangling);
+ MicrosoftCXXNameMangler Extra(Context, Stream);
+ Stream << "?$";
+ if (T->isUnsigned())
+ Extra.mangleSourceName("_UExtInt");
+ else
+ Extra.mangleSourceName("_ExtInt");
+ Extra.mangleIntegerLiteral(llvm::APSInt::getUnsigned(T->getNumBits()),
+ /*IsBoolean=*/false);
+
+ mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__clang"});
+}
+
+void MicrosoftCXXNameMangler::mangleType(const DependentExtIntType *T,
+ Qualifiers, SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(
+ DiagnosticsEngine::Error, "cannot mangle this DependentExtInt type yet");
+ Diags.Report(Range.getBegin(), DiagID) << Range;
+}
+
// <this-adjustment> ::= <no-adjustment> | <static-adjustment> |
// <virtual-adjustment>
// <no-adjustment> ::= A # private near
@@ -3218,7 +3248,7 @@ void MicrosoftMangleContextImpl::mangleCXXCatchableType(
if (!OmitCopyCtor && CD) {
llvm::raw_svector_ostream Stream(CopyCtorMangling);
msvc_hashing_ostream MHO(Stream);
- mangleCXXCtor(CD, CT, MHO);
+ mangleCXXName(GlobalDecl(CD, CT), MHO);
}
Mangler.getStream() << CopyCtorMangling;
@@ -3321,22 +3351,6 @@ void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) {
Mangler.mangleType(T, SourceRange());
}
-void MicrosoftMangleContextImpl::mangleCXXCtor(const CXXConstructorDecl *D,
- CXXCtorType Type,
- raw_ostream &Out) {
- msvc_hashing_ostream MHO(Out);
- MicrosoftCXXNameMangler mangler(*this, MHO, D, Type);
- mangler.mangle(D);
-}
-
-void MicrosoftMangleContextImpl::mangleCXXDtor(const CXXDestructorDecl *D,
- CXXDtorType Type,
- raw_ostream &Out) {
- msvc_hashing_ostream MHO(Out);
- MicrosoftCXXNameMangler mangler(*this, MHO, D, Type);
- mangler.mangle(D);
-}
-
void MicrosoftMangleContextImpl::mangleReferenceTemporary(
const VarDecl *VD, unsigned ManglingNumber, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
diff --git a/clang/lib/AST/NSAPI.cpp b/clang/lib/AST/NSAPI.cpp
index ae6ff04f5126d..ace7f1ceebe74 100644
--- a/clang/lib/AST/NSAPI.cpp
+++ b/clang/lib/AST/NSAPI.cpp
@@ -482,7 +482,11 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
case BuiltinType::Half:
case BuiltinType::PseudoObject:
case BuiltinType::BuiltinFn:
+ case BuiltinType::IncompleteMatrixIdx:
case BuiltinType::OMPArraySection:
+ case BuiltinType::OMPArrayShaping:
+ case BuiltinType::OMPIterator:
+ case BuiltinType::BFloat16:
break;
}
diff --git a/clang/lib/AST/NestedNameSpecifier.cpp b/clang/lib/AST/NestedNameSpecifier.cpp
index 137953fa8203a..08e8819a4d69d 100644
--- a/clang/lib/AST/NestedNameSpecifier.cpp
+++ b/clang/lib/AST/NestedNameSpecifier.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DependenceFlags.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
@@ -197,75 +198,53 @@ CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const {
llvm_unreachable("Invalid NNS Kind!");
}
-/// Whether this nested name specifier refers to a dependent
-/// type or not.
-bool NestedNameSpecifier::isDependent() const {
+NestedNameSpecifierDependence NestedNameSpecifier::getDependence() const {
switch (getKind()) {
- case Identifier:
+ case Identifier: {
// Identifier specifiers always represent dependent types
- return true;
+ auto F = NestedNameSpecifierDependence::Dependent |
+ NestedNameSpecifierDependence::Instantiation;
+ // Prefix can contain unexpanded template parameters.
+ if (getPrefix())
+ return F | getPrefix()->getDependence();
+ return F;
+ }
case Namespace:
case NamespaceAlias:
case Global:
- return false;
+ return NestedNameSpecifierDependence::None;
case Super: {
CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier);
for (const auto &Base : RD->bases())
if (Base.getType()->isDependentType())
- return true;
-
- return false;
+ // FIXME: must also be instantiation-dependent.
+ return NestedNameSpecifierDependence::Dependent;
+ return NestedNameSpecifierDependence::None;
}
case TypeSpec:
case TypeSpecWithTemplate:
- return getAsType()->isDependentType();
+ return toNestedNameSpecifierDependendence(getAsType()->getDependence());
}
-
llvm_unreachable("Invalid NNS Kind!");
}
-/// Whether this nested name specifier refers to a dependent
-/// type or not.
-bool NestedNameSpecifier::isInstantiationDependent() const {
- switch (getKind()) {
- case Identifier:
- // Identifier specifiers always represent dependent types
- return true;
-
- case Namespace:
- case NamespaceAlias:
- case Global:
- case Super:
- return false;
-
- case TypeSpec:
- case TypeSpecWithTemplate:
- return getAsType()->isInstantiationDependentType();
- }
+bool NestedNameSpecifier::isDependent() const {
+ return getDependence() & NestedNameSpecifierDependence::Dependent;
+}
- llvm_unreachable("Invalid NNS Kind!");
+bool NestedNameSpecifier::isInstantiationDependent() const {
+ return getDependence() & NestedNameSpecifierDependence::Instantiation;
}
bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
- switch (getKind()) {
- case Identifier:
- return getPrefix() && getPrefix()->containsUnexpandedParameterPack();
-
- case Namespace:
- case NamespaceAlias:
- case Global:
- case Super:
- return false;
-
- case TypeSpec:
- case TypeSpecWithTemplate:
- return getAsType()->containsUnexpandedParameterPack();
- }
+ return getDependence() & NestedNameSpecifierDependence::UnexpandedPack;
+}
- llvm_unreachable("Invalid NNS Kind!");
+bool NestedNameSpecifier::containsErrors() const {
+ return getDependence() & NestedNameSpecifierDependence::Error;
}
/// Print this nested name specifier to the given output
@@ -336,6 +315,14 @@ void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
// Print the template argument list.
printTemplateArgumentList(OS, SpecType->template_arguments(),
InnerPolicy);
+ } else if (const auto *DepSpecType =
+ dyn_cast<DependentTemplateSpecializationType>(T)) {
+ // Print the template name without its corresponding
+ // nested-name-specifier.
+ OS << DepSpecType->getIdentifier()->getName();
+ // Print the template argument list.
+ printTemplateArgumentList(OS, DepSpecType->template_arguments(),
+ InnerPolicy);
} else {
// Print the type normally
QualType(T, 0).print(OS, InnerPolicy);
@@ -481,12 +468,14 @@ static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
unsigned NewCapacity = std::max(
(unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2),
(unsigned)(BufferSize + (End - Start)));
- char *NewBuffer = static_cast<char *>(llvm::safe_malloc(NewCapacity));
- if (BufferCapacity) {
- memcpy(NewBuffer, Buffer, BufferSize);
- free(Buffer);
+ if (!BufferCapacity) {
+ char *NewBuffer = static_cast<char *>(llvm::safe_malloc(NewCapacity));
+ if (Buffer)
+ memcpy(NewBuffer, Buffer, BufferSize);
+ Buffer = NewBuffer;
+ } else {
+ Buffer = static_cast<char *>(llvm::safe_realloc(Buffer, NewCapacity));
}
- Buffer = NewBuffer;
BufferCapacity = NewCapacity;
}
assert(Buffer && Start && End && End > Start && "Illegal memory buffer copy");
diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp
index 27fdca1c4b9cf..735bcff8f1137 100644
--- a/clang/lib/AST/ODRHash.cpp
+++ b/clang/lib/AST/ODRHash.cpp
@@ -440,7 +440,7 @@ public:
// Only allow a small portion of Decl's to be processed. Remove this once
// all Decl's can be handled.
-bool ODRHash::isWhitelistedDecl(const Decl *D, const DeclContext *Parent) {
+bool ODRHash::isDeclToBeProcessed(const Decl *D, const DeclContext *Parent) {
if (D->isImplicit()) return false;
if (D->getDeclContext() != Parent) return false;
@@ -487,7 +487,7 @@ void ODRHash::AddCXXRecordDecl(const CXXRecordDecl *Record) {
// accurate count of Decl's.
llvm::SmallVector<const Decl *, 16> Decls;
for (Decl *SubDecl : Record->decls()) {
- if (isWhitelistedDecl(SubDecl, Record)) {
+ if (isDeclToBeProcessed(SubDecl, Record)) {
Decls.push_back(SubDecl);
if (auto *Function = dyn_cast<FunctionDecl>(SubDecl)) {
// Compute/Preload ODRHash into FunctionDecl.
@@ -588,7 +588,7 @@ void ODRHash::AddFunctionDecl(const FunctionDecl *Function,
// accurate count of Decl's.
llvm::SmallVector<const Decl *, 16> Decls;
for (Decl *SubDecl : Function->decls()) {
- if (isWhitelistedDecl(SubDecl, Function)) {
+ if (isDeclToBeProcessed(SubDecl, Function)) {
Decls.push_back(SubDecl);
}
}
@@ -614,7 +614,7 @@ void ODRHash::AddEnumDecl(const EnumDecl *Enum) {
// accurate count of Decl's.
llvm::SmallVector<const Decl *, 16> Decls;
for (Decl *SubDecl : Enum->decls()) {
- if (isWhitelistedDecl(SubDecl, Enum)) {
+ if (isDeclToBeProcessed(SubDecl, Enum)) {
assert(isa<EnumConstantDecl>(SubDecl) && "Unexpected Decl");
Decls.push_back(SubDecl);
}
@@ -857,6 +857,13 @@ public:
void VisitAutoType(const AutoType *T) {
ID.AddInteger((unsigned)T->getKeyword());
+ ID.AddInteger(T->isConstrained());
+ if (T->isConstrained()) {
+ AddDecl(T->getTypeConstraintConcept());
+ ID.AddInteger(T->getNumArgs());
+ for (const auto &TA : T->getTypeConstraintArguments())
+ Hash.AddTemplateArgument(TA);
+ }
VisitDeducedType(T);
}
diff --git a/clang/lib/AST/OSLog.cpp b/clang/lib/AST/OSLog.cpp
index df2f808728cfb..094c0102854b1 100644
--- a/clang/lib/AST/OSLog.cpp
+++ b/clang/lib/AST/OSLog.cpp
@@ -55,9 +55,9 @@ public:
ArgsData.reserve(Args.size());
}
- virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
- const char *StartSpecifier,
- unsigned SpecifierLen) {
+ bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
+ const char *StartSpecifier,
+ unsigned SpecifierLen) override {
if (!FS.consumesDataArgument() &&
FS.getConversionSpecifier().getKind() !=
clang::analyze_format_string::ConversionSpecifier::PrintErrno)
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index 5ef82648c89d1..a0b0dca553907 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -12,6 +12,7 @@
#include "clang/AST/OpenMPClause.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclOpenMP.h"
#include "clang/Basic/LLVM.h"
@@ -23,31 +24,35 @@
#include <cassert>
using namespace clang;
+using namespace llvm;
+using namespace omp;
OMPClause::child_range OMPClause::children() {
switch (getClauseKind()) {
default:
break;
-#define OPENMP_CLAUSE(Name, Class) \
- case OMPC_##Name: \
+#define OMP_CLAUSE_CLASS(Enum, Str, Class) \
+ case Enum: \
return static_cast<Class *>(this)->children();
-#include "clang/Basic/OpenMPKinds.def"
+#include "llvm/Frontend/OpenMP/OMPKinds.def"
}
llvm_unreachable("unknown OMPClause");
}
OMPClause::child_range OMPClause::used_children() {
switch (getClauseKind()) {
-#define OPENMP_CLAUSE(Name, Class) \
- case OMPC_##Name: \
+#define OMP_CLAUSE_CLASS(Enum, Str, Class) \
+ case Enum: \
return static_cast<Class *>(this)->used_children();
-#include "clang/Basic/OpenMPKinds.def"
+#include "llvm/Frontend/OpenMP/OMPKinds.def"
case OMPC_threadprivate:
case OMPC_uniform:
case OMPC_device_type:
case OMPC_match:
case OMPC_unknown:
break;
+ default:
+ break;
}
llvm_unreachable("unknown OMPClause");
}
@@ -111,11 +116,16 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
case OMPC_mergeable:
case OMPC_threadprivate:
case OMPC_flush:
+ case OMPC_depobj:
case OMPC_read:
case OMPC_write:
case OMPC_update:
case OMPC_capture:
case OMPC_seq_cst:
+ case OMPC_acq_rel:
+ case OMPC_acquire:
+ case OMPC_release:
+ case OMPC_relaxed:
case OMPC_depend:
case OMPC_threads:
case OMPC_simd:
@@ -128,6 +138,7 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
case OMPC_to:
case OMPC_from:
case OMPC_use_device_ptr:
+ case OMPC_use_device_addr:
case OMPC_is_device_ptr:
case OMPC_unified_address:
case OMPC_unified_shared_memory:
@@ -137,6 +148,15 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
case OMPC_device_type:
case OMPC_match:
case OMPC_nontemporal:
+ case OMPC_order:
+ case OMPC_destroy:
+ case OMPC_detach:
+ case OMPC_inclusive:
+ case OMPC_exclusive:
+ case OMPC_uses_allocators:
+ case OMPC_affinity:
+ break;
+ default:
break;
}
@@ -184,11 +204,16 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C)
case OMPC_mergeable:
case OMPC_threadprivate:
case OMPC_flush:
+ case OMPC_depobj:
case OMPC_read:
case OMPC_write:
case OMPC_update:
case OMPC_capture:
case OMPC_seq_cst:
+ case OMPC_acq_rel:
+ case OMPC_acquire:
+ case OMPC_release:
+ case OMPC_relaxed:
case OMPC_depend:
case OMPC_device:
case OMPC_threads:
@@ -207,6 +232,7 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C)
case OMPC_to:
case OMPC_from:
case OMPC_use_device_ptr:
+ case OMPC_use_device_addr:
case OMPC_is_device_ptr:
case OMPC_unified_address:
case OMPC_unified_shared_memory:
@@ -216,6 +242,15 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C)
case OMPC_device_type:
case OMPC_match:
case OMPC_nontemporal:
+ case OMPC_order:
+ case OMPC_destroy:
+ case OMPC_detach:
+ case OMPC_inclusive:
+ case OMPC_exclusive:
+ case OMPC_uses_allocators:
+ case OMPC_affinity:
+ break;
+ default:
break;
}
@@ -316,6 +351,39 @@ const Expr *OMPOrderedClause::getLoopCounter(unsigned NumLoop) const {
return getTrailingObjects<Expr *>()[NumberOfLoops + NumLoop];
}
+OMPUpdateClause *OMPUpdateClause::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return new (C) OMPUpdateClause(StartLoc, EndLoc, /*IsExtended=*/false);
+}
+
+OMPUpdateClause *
+OMPUpdateClause::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation ArgumentLoc,
+ OpenMPDependClauseKind DK, SourceLocation EndLoc) {
+ void *Mem =
+ C.Allocate(totalSizeToAlloc<SourceLocation, OpenMPDependClauseKind>(2, 1),
+ alignof(OMPUpdateClause));
+ auto *Clause =
+ new (Mem) OMPUpdateClause(StartLoc, EndLoc, /*IsExtended=*/true);
+ Clause->setLParenLoc(LParenLoc);
+ Clause->setArgumentLoc(ArgumentLoc);
+ Clause->setDependencyKind(DK);
+ return Clause;
+}
+
+OMPUpdateClause *OMPUpdateClause::CreateEmpty(const ASTContext &C,
+ bool IsExtended) {
+ if (!IsExtended)
+ return new (C) OMPUpdateClause(/*IsExtended=*/false);
+ void *Mem =
+ C.Allocate(totalSizeToAlloc<SourceLocation, OpenMPDependClauseKind>(2, 1),
+ alignof(OMPUpdateClause));
+ auto *Clause = new (Mem) OMPUpdateClause(/*IsExtended=*/true);
+ Clause->IsExtended = true;
+ return Clause;
+}
+
void OMPPrivateClause::setPrivateCopies(ArrayRef<Expr *> VL) {
assert(VL.size() == varlist_size() &&
"Number of private copies is not the same as the preallocated buffer");
@@ -647,16 +715,46 @@ void OMPReductionClause::setReductionOps(ArrayRef<Expr *> ReductionOps) {
std::copy(ReductionOps.begin(), ReductionOps.end(), getRHSExprs().end());
}
+void OMPReductionClause::setInscanCopyOps(ArrayRef<Expr *> Ops) {
+ assert(Modifier == OMPC_REDUCTION_inscan && "Expected inscan reduction.");
+ assert(Ops.size() == varlist_size() && "Number of copy "
+ "expressions is not the same "
+ "as the preallocated buffer");
+ llvm::copy(Ops, getReductionOps().end());
+}
+
+void OMPReductionClause::setInscanCopyArrayTemps(
+ ArrayRef<Expr *> CopyArrayTemps) {
+ assert(Modifier == OMPC_REDUCTION_inscan && "Expected inscan reduction.");
+ assert(CopyArrayTemps.size() == varlist_size() &&
+ "Number of copy temp expressions is not the same as the preallocated "
+ "buffer");
+ llvm::copy(CopyArrayTemps, getInscanCopyOps().end());
+}
+
+void OMPReductionClause::setInscanCopyArrayElems(
+ ArrayRef<Expr *> CopyArrayElems) {
+ assert(Modifier == OMPC_REDUCTION_inscan && "Expected inscan reduction.");
+ assert(CopyArrayElems.size() == varlist_size() &&
+ "Number of copy temp expressions is not the same as the preallocated "
+ "buffer");
+ llvm::copy(CopyArrayElems, getInscanCopyArrayTemps().end());
+}
+
OMPReductionClause *OMPReductionClause::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL,
+ SourceLocation ModifierLoc, SourceLocation EndLoc, SourceLocation ColonLoc,
+ OpenMPReductionClauseModifier Modifier, ArrayRef<Expr *> VL,
NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
ArrayRef<Expr *> Privates, ArrayRef<Expr *> LHSExprs,
- ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps, Stmt *PreInit,
- Expr *PostUpdate) {
- void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size()));
- OMPReductionClause *Clause = new (Mem) OMPReductionClause(
- StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo);
+ ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps,
+ ArrayRef<Expr *> CopyOps, ArrayRef<Expr *> CopyArrayTemps,
+ ArrayRef<Expr *> CopyArrayElems, Stmt *PreInit, Expr *PostUpdate) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(
+ (Modifier == OMPC_REDUCTION_inscan ? 8 : 5) * VL.size()));
+ auto *Clause = new (Mem)
+ OMPReductionClause(StartLoc, LParenLoc, ModifierLoc, EndLoc, ColonLoc,
+ Modifier, VL.size(), QualifierLoc, NameInfo);
Clause->setVarRefs(VL);
Clause->setPrivates(Privates);
Clause->setLHSExprs(LHSExprs);
@@ -664,13 +762,29 @@ OMPReductionClause *OMPReductionClause::Create(
Clause->setReductionOps(ReductionOps);
Clause->setPreInitStmt(PreInit);
Clause->setPostUpdateExpr(PostUpdate);
+ if (Modifier == OMPC_REDUCTION_inscan) {
+ Clause->setInscanCopyOps(CopyOps);
+ Clause->setInscanCopyArrayTemps(CopyArrayTemps);
+ Clause->setInscanCopyArrayElems(CopyArrayElems);
+ } else {
+ assert(CopyOps.empty() &&
+ "copy operations are expected in inscan reductions only.");
+ assert(CopyArrayTemps.empty() &&
+ "copy array temps are expected in inscan reductions only.");
+ assert(CopyArrayElems.empty() &&
+ "copy array temps are expected in inscan reductions only.");
+ }
return Clause;
}
-OMPReductionClause *OMPReductionClause::CreateEmpty(const ASTContext &C,
- unsigned N) {
- void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * N));
- return new (Mem) OMPReductionClause(N);
+OMPReductionClause *
+OMPReductionClause::CreateEmpty(const ASTContext &C, unsigned N,
+ OpenMPReductionClauseModifier Modifier) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(
+ (Modifier == OMPC_REDUCTION_inscan ? 8 : 5) * N));
+ auto *Clause = new (Mem) OMPReductionClause(N);
+ Clause->setModifier(Modifier);
+ return Clause;
}
void OMPTaskReductionClause::setPrivates(ArrayRef<Expr *> Privates) {
@@ -825,19 +939,36 @@ OMPFlushClause *OMPFlushClause::CreateEmpty(const ASTContext &C, unsigned N) {
return new (Mem) OMPFlushClause(N);
}
+OMPDepobjClause *OMPDepobjClause::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc,
+ Expr *Depobj) {
+ auto *Clause = new (C) OMPDepobjClause(StartLoc, LParenLoc, RParenLoc);
+ Clause->setDepobj(Depobj);
+ return Clause;
+}
+
+OMPDepobjClause *OMPDepobjClause::CreateEmpty(const ASTContext &C) {
+ return new (C) OMPDepobjClause();
+}
+
OMPDependClause *
OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc,
- OpenMPDependClauseKind DepKind, SourceLocation DepLoc,
- SourceLocation ColonLoc, ArrayRef<Expr *> VL,
- unsigned NumLoops) {
- void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size() + NumLoops));
+ Expr *DepModifier, OpenMPDependClauseKind DepKind,
+ SourceLocation DepLoc, SourceLocation ColonLoc,
+ ArrayRef<Expr *> VL, unsigned NumLoops) {
+ void *Mem = C.Allocate(
+ totalSizeToAlloc<Expr *>(VL.size() + /*depend-modifier*/ 1 + NumLoops),
+ alignof(OMPDependClause));
OMPDependClause *Clause = new (Mem)
OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size(), NumLoops);
Clause->setVarRefs(VL);
Clause->setDependencyKind(DepKind);
Clause->setDependencyLoc(DepLoc);
Clause->setColonLoc(ColonLoc);
+ Clause->setModifier(DepModifier);
for (unsigned I = 0 ; I < NumLoops; ++I)
Clause->setLoopData(I, nullptr);
return Clause;
@@ -845,7 +976,9 @@ OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc,
OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N,
unsigned NumLoops) {
- void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N + NumLoops));
+ void *Mem =
+ C.Allocate(totalSizeToAlloc<Expr *>(N + /*depend-modifier*/ 1 + NumLoops),
+ alignof(OMPDependClause));
return new (Mem) OMPDependClause(N, NumLoops);
}
@@ -855,7 +988,7 @@ void OMPDependClause::setLoopData(unsigned NumLoop, Expr *Cnt) {
NumLoop < NumLoops &&
"Expected sink or source depend + loop index must be less number of "
"loops.");
- auto It = std::next(getVarRefs().end(), NumLoop);
+ auto *It = std::next(getVarRefs().end(), NumLoop + 1);
*It = Cnt;
}
@@ -865,7 +998,7 @@ Expr *OMPDependClause::getLoopData(unsigned NumLoop) {
NumLoop < NumLoops &&
"Expected sink or source depend + loop index must be less number of "
"loops.");
- auto It = std::next(getVarRefs().end(), NumLoop);
+ auto *It = std::next(getVarRefs().end(), NumLoop + 1);
return *It;
}
@@ -875,10 +1008,15 @@ const Expr *OMPDependClause::getLoopData(unsigned NumLoop) const {
NumLoop < NumLoops &&
"Expected sink or source depend + loop index must be less number of "
"loops.");
- auto It = std::next(getVarRefs().end(), NumLoop);
+ const auto *It = std::next(getVarRefs().end(), NumLoop + 1);
return *It;
}
+void OMPDependClause::setModifier(Expr *DepModifier) {
+ *getVarRefs().end() = DepModifier;
+}
+Expr *OMPDependClause::getModifier() { return *getVarRefs().end(); }
+
unsigned OMPClauseMappableExprCommon::getComponentsTotalNumber(
MappableExprComponentListsRef ComponentLists) {
unsigned TotalNum = 0u;
@@ -1075,8 +1213,8 @@ OMPUseDevicePtrClause *OMPUseDevicePtrClause::Create(
Sizes.NumComponents = getComponentsTotalNumber(ComponentLists);
// We need to allocate:
- // 3 x NumVars x Expr* - we have an original list expression for each clause
- // list entry and an equal number of private copies and inits.
+ // NumVars x Expr* - we have an original list expression for each clause
+ // list entry.
// NumUniqueDeclarations x ValueDecl* - unique base declarations associated
// with each component list.
// (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
@@ -1112,6 +1250,53 @@ OMPUseDevicePtrClause::CreateEmpty(const ASTContext &C,
return new (Mem) OMPUseDevicePtrClause(Sizes);
}
+OMPUseDeviceAddrClause *
+OMPUseDeviceAddrClause::Create(const ASTContext &C, const OMPVarListLocTy &Locs,
+ ArrayRef<Expr *> Vars,
+ ArrayRef<ValueDecl *> Declarations,
+ MappableExprComponentListsRef ComponentLists) {
+ OMPMappableExprListSizeTy Sizes;
+ Sizes.NumVars = Vars.size();
+ Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations);
+ Sizes.NumComponentLists = ComponentLists.size();
+ Sizes.NumComponents = getComponentsTotalNumber(ComponentLists);
+
+ // We need to allocate:
+ // 3 x NumVars x Expr* - we have an original list expression for each clause
+ // list entry and an equal number of private copies and inits.
+ // NumUniqueDeclarations x ValueDecl* - unique base declarations associated
+ // with each component list.
+ // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
+ // number of lists for each unique declaration and the size of each component
+ // list.
+ // NumComponents x MappableComponent - the total of all the components in all
+ // the lists.
+ void *Mem = C.Allocate(
+ totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ OMPClauseMappableExprCommon::MappableComponent>(
+ Sizes.NumVars, Sizes.NumUniqueDeclarations,
+ Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
+ Sizes.NumComponents));
+
+ auto *Clause = new (Mem) OMPUseDeviceAddrClause(Locs, Sizes);
+
+ Clause->setVarRefs(Vars);
+ Clause->setClauseInfo(Declarations, ComponentLists);
+ return Clause;
+}
+
+OMPUseDeviceAddrClause *
+OMPUseDeviceAddrClause::CreateEmpty(const ASTContext &C,
+ const OMPMappableExprListSizeTy &Sizes) {
+ void *Mem = C.Allocate(
+ totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ OMPClauseMappableExprCommon::MappableComponent>(
+ Sizes.NumVars, Sizes.NumUniqueDeclarations,
+ Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
+ Sizes.NumComponents));
+ return new (Mem) OMPUseDeviceAddrClause(Sizes);
+}
+
OMPIsDevicePtrClause *
OMPIsDevicePtrClause::Create(const ASTContext &C, const OMPVarListLocTy &Locs,
ArrayRef<Expr *> Vars,
@@ -1184,13 +1369,132 @@ void OMPNontemporalClause::setPrivateRefs(ArrayRef<Expr *> VL) {
std::copy(VL.begin(), VL.end(), varlist_end());
}
+OMPInclusiveClause *OMPInclusiveClause::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc,
+ ArrayRef<Expr *> VL) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size()));
+ auto *Clause =
+ new (Mem) OMPInclusiveClause(StartLoc, LParenLoc, EndLoc, VL.size());
+ Clause->setVarRefs(VL);
+ return Clause;
+}
+
+OMPInclusiveClause *OMPInclusiveClause::CreateEmpty(const ASTContext &C,
+ unsigned N) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
+ return new (Mem) OMPInclusiveClause(N);
+}
+
+OMPExclusiveClause *OMPExclusiveClause::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc,
+ ArrayRef<Expr *> VL) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size()));
+ auto *Clause =
+ new (Mem) OMPExclusiveClause(StartLoc, LParenLoc, EndLoc, VL.size());
+ Clause->setVarRefs(VL);
+ return Clause;
+}
+
+OMPExclusiveClause *OMPExclusiveClause::CreateEmpty(const ASTContext &C,
+ unsigned N) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
+ return new (Mem) OMPExclusiveClause(N);
+}
+
+void OMPUsesAllocatorsClause::setAllocatorsData(
+ ArrayRef<OMPUsesAllocatorsClause::Data> Data) {
+ assert(Data.size() == NumOfAllocators &&
+ "Size of allocators data is not the same as the preallocated buffer.");
+ for (unsigned I = 0, E = Data.size(); I < E; ++I) {
+ const OMPUsesAllocatorsClause::Data &D = Data[I];
+ getTrailingObjects<Expr *>()[I * static_cast<int>(ExprOffsets::Total) +
+ static_cast<int>(ExprOffsets::Allocator)] =
+ D.Allocator;
+ getTrailingObjects<Expr *>()[I * static_cast<int>(ExprOffsets::Total) +
+ static_cast<int>(
+ ExprOffsets::AllocatorTraits)] =
+ D.AllocatorTraits;
+ getTrailingObjects<
+ SourceLocation>()[I * static_cast<int>(ParenLocsOffsets::Total) +
+ static_cast<int>(ParenLocsOffsets::LParen)] =
+ D.LParenLoc;
+ getTrailingObjects<
+ SourceLocation>()[I * static_cast<int>(ParenLocsOffsets::Total) +
+ static_cast<int>(ParenLocsOffsets::RParen)] =
+ D.RParenLoc;
+ }
+}
+
+OMPUsesAllocatorsClause::Data
+OMPUsesAllocatorsClause::getAllocatorData(unsigned I) const {
+ OMPUsesAllocatorsClause::Data Data;
+ Data.Allocator =
+ getTrailingObjects<Expr *>()[I * static_cast<int>(ExprOffsets::Total) +
+ static_cast<int>(ExprOffsets::Allocator)];
+ Data.AllocatorTraits =
+ getTrailingObjects<Expr *>()[I * static_cast<int>(ExprOffsets::Total) +
+ static_cast<int>(
+ ExprOffsets::AllocatorTraits)];
+ Data.LParenLoc = getTrailingObjects<
+ SourceLocation>()[I * static_cast<int>(ParenLocsOffsets::Total) +
+ static_cast<int>(ParenLocsOffsets::LParen)];
+ Data.RParenLoc = getTrailingObjects<
+ SourceLocation>()[I * static_cast<int>(ParenLocsOffsets::Total) +
+ static_cast<int>(ParenLocsOffsets::RParen)];
+ return Data;
+}
+
+OMPUsesAllocatorsClause *
+OMPUsesAllocatorsClause::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc,
+ ArrayRef<OMPUsesAllocatorsClause::Data> Data) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *, SourceLocation>(
+ static_cast<int>(ExprOffsets::Total) * Data.size(),
+ static_cast<int>(ParenLocsOffsets::Total) * Data.size()));
+ auto *Clause = new (Mem)
+ OMPUsesAllocatorsClause(StartLoc, LParenLoc, EndLoc, Data.size());
+ Clause->setAllocatorsData(Data);
+ return Clause;
+}
+
+OMPUsesAllocatorsClause *
+OMPUsesAllocatorsClause::CreateEmpty(const ASTContext &C, unsigned N) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *, SourceLocation>(
+ static_cast<int>(ExprOffsets::Total) * N,
+ static_cast<int>(ParenLocsOffsets::Total) * N));
+ return new (Mem) OMPUsesAllocatorsClause(N);
+}
+
+OMPAffinityClause *
+OMPAffinityClause::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation ColonLoc,
+ SourceLocation EndLoc, Expr *Modifier,
+ ArrayRef<Expr *> Locators) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(Locators.size() + 1));
+ auto *Clause = new (Mem)
+ OMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc, Locators.size());
+ Clause->setModifier(Modifier);
+ Clause->setVarRefs(Locators);
+ return Clause;
+}
+
+OMPAffinityClause *OMPAffinityClause::CreateEmpty(const ASTContext &C,
+ unsigned N) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N + 1));
+ return new (Mem) OMPAffinityClause(N);
+}
+
//===----------------------------------------------------------------------===//
// OpenMP clauses printing methods
//===----------------------------------------------------------------------===//
void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) {
OS << "if(";
- if (Node->getNameModifier() != llvm::omp::OMPD_unknown)
+ if (Node->getNameModifier() != OMPD_unknown)
OS << getOpenMPDirectiveName(Node->getNameModifier()) << ": ";
Node->getCondition()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
@@ -1232,9 +1536,16 @@ void OMPClausePrinter::VisitOMPCollapseClause(OMPCollapseClause *Node) {
OS << ")";
}
+void OMPClausePrinter::VisitOMPDetachClause(OMPDetachClause *Node) {
+ OS << "detach(";
+ Node->getEventHandler()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
void OMPClausePrinter::VisitOMPDefaultClause(OMPDefaultClause *Node) {
OS << "default("
- << getOpenMPSimpleClauseTypeName(OMPC_default, Node->getDefaultKind())
+ << getOpenMPSimpleClauseTypeName(OMPC_default,
+ unsigned(Node->getDefaultKind()))
<< ")";
}
@@ -1320,8 +1631,14 @@ void OMPClausePrinter::VisitOMPReadClause(OMPReadClause *) { OS << "read"; }
void OMPClausePrinter::VisitOMPWriteClause(OMPWriteClause *) { OS << "write"; }
-void OMPClausePrinter::VisitOMPUpdateClause(OMPUpdateClause *) {
+void OMPClausePrinter::VisitOMPUpdateClause(OMPUpdateClause *Node) {
OS << "update";
+ if (Node->isExtended()) {
+ OS << "(";
+ OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(),
+ Node->getDependencyKind());
+ OS << ")";
+ }
}
void OMPClausePrinter::VisitOMPCaptureClause(OMPCaptureClause *) {
@@ -1332,6 +1649,22 @@ void OMPClausePrinter::VisitOMPSeqCstClause(OMPSeqCstClause *) {
OS << "seq_cst";
}
+void OMPClausePrinter::VisitOMPAcqRelClause(OMPAcqRelClause *) {
+ OS << "acq_rel";
+}
+
+void OMPClausePrinter::VisitOMPAcquireClause(OMPAcquireClause *) {
+ OS << "acquire";
+}
+
+void OMPClausePrinter::VisitOMPReleaseClause(OMPReleaseClause *) {
+ OS << "release";
+}
+
+void OMPClausePrinter::VisitOMPRelaxedClause(OMPRelaxedClause *) {
+ OS << "relaxed";
+}
+
void OMPClausePrinter::VisitOMPThreadsClause(OMPThreadsClause *) {
OS << "threads";
}
@@ -1340,6 +1673,11 @@ void OMPClausePrinter::VisitOMPSIMDClause(OMPSIMDClause *) { OS << "simd"; }
void OMPClausePrinter::VisitOMPDeviceClause(OMPDeviceClause *Node) {
OS << "device(";
+ OpenMPDeviceClauseModifier Modifier = Node->getModifier();
+ if (Modifier != OMPC_DEVICE_unknown) {
+ OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), Modifier)
+ << ": ";
+ }
Node->getDevice()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
@@ -1380,6 +1718,10 @@ void OMPClausePrinter::VisitOMPHintClause(OMPHintClause *Node) {
OS << ")";
}
+void OMPClausePrinter::VisitOMPDestroyClause(OMPDestroyClause *) {
+ OS << "destroy";
+}
+
template<typename T>
void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) {
for (typename T::varlist_iterator I = Node->varlist_begin(),
@@ -1453,6 +1795,9 @@ void OMPClausePrinter::VisitOMPSharedClause(OMPSharedClause *Node) {
void OMPClausePrinter::VisitOMPReductionClause(OMPReductionClause *Node) {
if (!Node->varlist_empty()) {
OS << "reduction(";
+ if (Node->getModifierLoc().isValid())
+ OS << getOpenMPSimpleClauseTypeName(OMPC_reduction, Node->getModifier())
+ << ", ";
NestedNameSpecifier *QualifierLoc =
Node->getQualifierLoc().getNestedNameSpecifier();
OverloadedOperatorKind OOK =
@@ -1570,8 +1915,18 @@ void OMPClausePrinter::VisitOMPFlushClause(OMPFlushClause *Node) {
}
}
+void OMPClausePrinter::VisitOMPDepobjClause(OMPDepobjClause *Node) {
+ OS << "(";
+ Node->getDepobj()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
void OMPClausePrinter::VisitOMPDependClause(OMPDependClause *Node) {
OS << "depend(";
+ if (Expr *DepModifier = Node->getModifier()) {
+ DepModifier->printPretty(OS, nullptr, Policy);
+ OS << ", ";
+ }
OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(),
Node->getDependencyKind());
if (!Node->varlist_empty()) {
@@ -1585,7 +1940,7 @@ void OMPClausePrinter::VisitOMPMapClause(OMPMapClause *Node) {
if (!Node->varlist_empty()) {
OS << "map(";
if (Node->getMapType() != OMPC_MAP_unknown) {
- for (unsigned I = 0; I < OMPMapClause::NumberOfModifiers; ++I) {
+ for (unsigned I = 0; I < NumberOfOMPMapClauseModifiers; ++I) {
if (Node->getMapTypeModifier(I) != OMPC_MAP_MODIFIER_unknown) {
OS << getOpenMPSimpleClauseTypeName(OMPC_map,
Node->getMapTypeModifier(I));
@@ -1662,9 +2017,11 @@ void OMPClausePrinter::VisitOMPDefaultmapClause(OMPDefaultmapClause *Node) {
OS << "defaultmap(";
OS << getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
Node->getDefaultmapModifier());
- OS << ": ";
- OS << getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
- Node->getDefaultmapKind());
+ if (Node->getDefaultmapKind() != OMPC_DEFAULTMAP_unknown) {
+ OS << ": ";
+ OS << getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
+ Node->getDefaultmapKind());
+ }
OS << ")";
}
@@ -1676,6 +2033,15 @@ void OMPClausePrinter::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *Node) {
}
}
+void OMPClausePrinter::VisitOMPUseDeviceAddrClause(
+ OMPUseDeviceAddrClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "use_device_addr";
+ VisitOMPClauseList(Node, '(');
+ OS << ")";
+ }
+}
+
void OMPClausePrinter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *Node) {
if (!Node->varlist_empty()) {
OS << "is_device_ptr";
@@ -1691,3 +2057,226 @@ void OMPClausePrinter::VisitOMPNontemporalClause(OMPNontemporalClause *Node) {
OS << ")";
}
}
+
+void OMPClausePrinter::VisitOMPOrderClause(OMPOrderClause *Node) {
+ OS << "order(" << getOpenMPSimpleClauseTypeName(OMPC_order, Node->getKind())
+ << ")";
+}
+
+void OMPClausePrinter::VisitOMPInclusiveClause(OMPInclusiveClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "inclusive";
+ VisitOMPClauseList(Node, '(');
+ OS << ")";
+ }
+}
+
+void OMPClausePrinter::VisitOMPExclusiveClause(OMPExclusiveClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "exclusive";
+ VisitOMPClauseList(Node, '(');
+ OS << ")";
+ }
+}
+
+void OMPClausePrinter::VisitOMPUsesAllocatorsClause(
+ OMPUsesAllocatorsClause *Node) {
+ if (Node->getNumberOfAllocators() == 0)
+ return;
+ OS << "uses_allocators(";
+ for (unsigned I = 0, E = Node->getNumberOfAllocators(); I < E; ++I) {
+ OMPUsesAllocatorsClause::Data Data = Node->getAllocatorData(I);
+ Data.Allocator->printPretty(OS, nullptr, Policy);
+ if (Data.AllocatorTraits) {
+ OS << "(";
+ Data.AllocatorTraits->printPretty(OS, nullptr, Policy);
+ OS << ")";
+ }
+ if (I < E - 1)
+ OS << ",";
+ }
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPAffinityClause(OMPAffinityClause *Node) {
+ if (Node->varlist_empty())
+ return;
+ OS << "affinity";
+ char StartSym = '(';
+ if (Expr *Modifier = Node->getModifier()) {
+ OS << "(";
+ Modifier->printPretty(OS, nullptr, Policy);
+ OS << " :";
+ StartSym = ' ';
+ }
+ VisitOMPClauseList(Node, StartSym);
+ OS << ")";
+}
+
+void OMPTraitInfo::getAsVariantMatchInfo(ASTContext &ASTCtx,
+ VariantMatchInfo &VMI) const {
+ for (const OMPTraitSet &Set : Sets) {
+ for (const OMPTraitSelector &Selector : Set.Selectors) {
+
+ // User conditions are special as we evaluate the condition here.
+ if (Selector.Kind == TraitSelector::user_condition) {
+ assert(Selector.ScoreOrCondition &&
+ "Ill-formed user condition, expected condition expression!");
+ assert(Selector.Properties.size() == 1 &&
+ Selector.Properties.front().Kind ==
+ TraitProperty::user_condition_unknown &&
+ "Ill-formed user condition, expected unknown trait property!");
+
+ llvm::APSInt CondVal;
+ if (Selector.ScoreOrCondition->isIntegerConstantExpr(CondVal, ASTCtx))
+ VMI.addTrait(CondVal.isNullValue()
+ ? TraitProperty::user_condition_false
+ : TraitProperty::user_condition_true);
+ else
+ VMI.addTrait(TraitProperty::user_condition_false);
+ continue;
+ }
+
+ llvm::APSInt Score;
+ llvm::APInt *ScorePtr = nullptr;
+ if (Selector.ScoreOrCondition) {
+ if (Selector.ScoreOrCondition->isIntegerConstantExpr(Score, ASTCtx))
+ ScorePtr = &Score;
+ else
+ VMI.addTrait(TraitProperty::user_condition_false);
+ }
+
+ for (const OMPTraitProperty &Property : Selector.Properties)
+ VMI.addTrait(Set.Kind, Property.Kind, ScorePtr);
+
+ if (Set.Kind != TraitSet::construct)
+ continue;
+
+ // TODO: This might not hold once we implement SIMD properly.
+ assert(Selector.Properties.size() == 1 &&
+ Selector.Properties.front().Kind ==
+ getOpenMPContextTraitPropertyForSelector(
+ Selector.Kind) &&
+ "Ill-formed construct selector!");
+
+ VMI.ConstructTraits.push_back(Selector.Properties.front().Kind);
+ }
+ }
+}
+
+void OMPTraitInfo::print(llvm::raw_ostream &OS,
+ const PrintingPolicy &Policy) const {
+ bool FirstSet = true;
+ for (const OMPTraitSet &Set : Sets) {
+ if (!FirstSet)
+ OS << ", ";
+ FirstSet = false;
+ OS << getOpenMPContextTraitSetName(Set.Kind) << "={";
+
+ bool FirstSelector = true;
+ for (const OMPTraitSelector &Selector : Set.Selectors) {
+ if (!FirstSelector)
+ OS << ", ";
+ FirstSelector = false;
+ OS << getOpenMPContextTraitSelectorName(Selector.Kind);
+
+ bool AllowsTraitScore = false;
+ bool RequiresProperty = false;
+ isValidTraitSelectorForTraitSet(
+ Selector.Kind, Set.Kind, AllowsTraitScore, RequiresProperty);
+
+ if (!RequiresProperty)
+ continue;
+
+ OS << "(";
+ if (Selector.Kind == TraitSelector::user_condition) {
+ Selector.ScoreOrCondition->printPretty(OS, nullptr, Policy);
+ } else {
+
+ if (Selector.ScoreOrCondition) {
+ OS << "score(";
+ Selector.ScoreOrCondition->printPretty(OS, nullptr, Policy);
+ OS << "): ";
+ }
+
+ bool FirstProperty = true;
+ for (const OMPTraitProperty &Property : Selector.Properties) {
+ if (!FirstProperty)
+ OS << ", ";
+ FirstProperty = false;
+ OS << getOpenMPContextTraitPropertyName(Property.Kind);
+ }
+ }
+ OS << ")";
+ }
+ OS << "}";
+ }
+}
+
+std::string OMPTraitInfo::getMangledName() const {
+ std::string MangledName;
+ llvm::raw_string_ostream OS(MangledName);
+ for (const OMPTraitSet &Set : Sets) {
+ OS << '$' << 'S' << unsigned(Set.Kind);
+ for (const OMPTraitSelector &Selector : Set.Selectors) {
+
+ bool AllowsTraitScore = false;
+ bool RequiresProperty = false;
+ isValidTraitSelectorForTraitSet(
+ Selector.Kind, Set.Kind, AllowsTraitScore, RequiresProperty);
+ OS << '$' << 's' << unsigned(Selector.Kind);
+
+ if (!RequiresProperty ||
+ Selector.Kind == TraitSelector::user_condition)
+ continue;
+
+ for (const OMPTraitProperty &Property : Selector.Properties)
+ OS << '$' << 'P' << getOpenMPContextTraitPropertyName(Property.Kind);
+ }
+ }
+ return OS.str();
+}
+
+OMPTraitInfo::OMPTraitInfo(StringRef MangledName) {
+ unsigned long U;
+ do {
+ if (!MangledName.consume_front("$S"))
+ break;
+ if (MangledName.consumeInteger(10, U))
+ break;
+ Sets.push_back(OMPTraitSet());
+ OMPTraitSet &Set = Sets.back();
+ Set.Kind = TraitSet(U);
+ do {
+ if (!MangledName.consume_front("$s"))
+ break;
+ if (MangledName.consumeInteger(10, U))
+ break;
+ Set.Selectors.push_back(OMPTraitSelector());
+ OMPTraitSelector &Selector = Set.Selectors.back();
+ Selector.Kind = TraitSelector(U);
+ do {
+ if (!MangledName.consume_front("$P"))
+ break;
+ Selector.Properties.push_back(OMPTraitProperty());
+ OMPTraitProperty &Property = Selector.Properties.back();
+ std::pair<StringRef, StringRef> PropRestPair = MangledName.split('$');
+ Property.Kind =
+ getOpenMPContextTraitPropertyKind(Set.Kind, PropRestPair.first);
+ MangledName = PropRestPair.second;
+ } while (true);
+ } while (true);
+ } while (true);
+}
+
+llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS,
+ const OMPTraitInfo &TI) {
+ LangOptions LO;
+ PrintingPolicy Policy(LO);
+ TI.print(OS, Policy);
+ return OS;
+}
+llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS,
+ const OMPTraitInfo *TI) {
+ return TI ? OS << *TI : OS;
+}
diff --git a/clang/lib/AST/ParentMapContext.cpp b/clang/lib/AST/ParentMapContext.cpp
new file mode 100644
index 0000000000000..b73b32774b53f
--- /dev/null
+++ b/clang/lib/AST/ParentMapContext.cpp
@@ -0,0 +1,321 @@
+//===- ParentMapContext.cpp - Map of parents using DynTypedNode -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Similar to ParentMap.cpp, but generalizes to non-Stmt nodes, which can have
+// multiple parents.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ParentMapContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/TemplateBase.h"
+
+using namespace clang;
+
+ParentMapContext::ParentMapContext(ASTContext &Ctx) : ASTCtx(Ctx) {}
+
+ParentMapContext::~ParentMapContext() = default;
+
+void ParentMapContext::clear() { Parents.reset(); }
+
+const Expr *ParentMapContext::traverseIgnored(const Expr *E) const {
+ return traverseIgnored(const_cast<Expr *>(E));
+}
+
+Expr *ParentMapContext::traverseIgnored(Expr *E) const {
+ if (!E)
+ return nullptr;
+
+ switch (Traversal) {
+ case TK_AsIs:
+ return E;
+ case TK_IgnoreImplicitCastsAndParentheses:
+ return E->IgnoreParenImpCasts();
+ case TK_IgnoreUnlessSpelledInSource:
+ return E->IgnoreUnlessSpelledInSource();
+ }
+ llvm_unreachable("Invalid Traversal type!");
+}
+
+DynTypedNode ParentMapContext::traverseIgnored(const DynTypedNode &N) const {
+ if (const auto *E = N.get<Expr>()) {
+ return DynTypedNode::create(*traverseIgnored(E));
+ }
+ return N;
+}
+
+class ParentMapContext::ParentMap {
+ /// Contains parents of a node.
+ using ParentVector = llvm::SmallVector<DynTypedNode, 2>;
+
+ /// Maps from a node to its parents. This is used for nodes that have
+ /// pointer identity only, which are more common and we can save space by
+ /// only storing a unique pointer to them.
+ using ParentMapPointers =
+ llvm::DenseMap<const void *,
+ llvm::PointerUnion<const Decl *, const Stmt *,
+ DynTypedNode *, ParentVector *>>;
+
+ /// Parent map for nodes without pointer identity. We store a full
+ /// DynTypedNode for all keys.
+ using ParentMapOtherNodes =
+ llvm::DenseMap<DynTypedNode,
+ llvm::PointerUnion<const Decl *, const Stmt *,
+ DynTypedNode *, ParentVector *>>;
+
+ ParentMapPointers PointerParents;
+ ParentMapOtherNodes OtherParents;
+ class ASTVisitor;
+
+ static DynTypedNode
+ getSingleDynTypedNodeFromParentMap(ParentMapPointers::mapped_type U) {
+ if (const auto *D = U.dyn_cast<const Decl *>())
+ return DynTypedNode::create(*D);
+ if (const auto *S = U.dyn_cast<const Stmt *>())
+ return DynTypedNode::create(*S);
+ return *U.get<DynTypedNode *>();
+ }
+
+ template <typename NodeTy, typename MapTy>
+ static DynTypedNodeList getDynNodeFromMap(const NodeTy &Node,
+ const MapTy &Map) {
+ auto I = Map.find(Node);
+ if (I == Map.end()) {
+ return llvm::ArrayRef<DynTypedNode>();
+ }
+ if (const auto *V = I->second.template dyn_cast<ParentVector *>()) {
+ return llvm::makeArrayRef(*V);
+ }
+ return getSingleDynTypedNodeFromParentMap(I->second);
+ }
+
+public:
+ ParentMap(ASTContext &Ctx);
+ ~ParentMap() {
+ for (const auto &Entry : PointerParents) {
+ if (Entry.second.is<DynTypedNode *>()) {
+ delete Entry.second.get<DynTypedNode *>();
+ } else if (Entry.second.is<ParentVector *>()) {
+ delete Entry.second.get<ParentVector *>();
+ }
+ }
+ for (const auto &Entry : OtherParents) {
+ if (Entry.second.is<DynTypedNode *>()) {
+ delete Entry.second.get<DynTypedNode *>();
+ } else if (Entry.second.is<ParentVector *>()) {
+ delete Entry.second.get<ParentVector *>();
+ }
+ }
+ }
+
+ DynTypedNodeList getParents(TraversalKind TK, const DynTypedNode &Node) {
+ if (Node.getNodeKind().hasPointerIdentity()) {
+ auto ParentList =
+ getDynNodeFromMap(Node.getMemoizationData(), PointerParents);
+ if (ParentList.size() == 1 && TK == TK_IgnoreUnlessSpelledInSource) {
+ const auto *E = ParentList[0].get<Expr>();
+ const auto *Child = Node.get<Expr>();
+ if (E && Child)
+ return AscendIgnoreUnlessSpelledInSource(E, Child);
+ }
+ return ParentList;
+ }
+ return getDynNodeFromMap(Node, OtherParents);
+ }
+
+ DynTypedNodeList AscendIgnoreUnlessSpelledInSource(const Expr *E,
+ const Expr *Child) {
+
+ auto ShouldSkip = [](const Expr *E, const Expr *Child) {
+ if (isa<ImplicitCastExpr>(E))
+ return true;
+
+ if (isa<FullExpr>(E))
+ return true;
+
+ if (isa<MaterializeTemporaryExpr>(E))
+ return true;
+
+ if (isa<CXXBindTemporaryExpr>(E))
+ return true;
+
+ if (isa<ParenExpr>(E))
+ return true;
+
+ if (isa<ExprWithCleanups>(E))
+ return true;
+
+ auto SR = Child->getSourceRange();
+
+ if (const auto *C = dyn_cast<CXXConstructExpr>(E)) {
+ if (C->getSourceRange() == SR || !isa<CXXTemporaryObjectExpr>(C))
+ return true;
+ }
+
+ if (const auto *C = dyn_cast<CXXMemberCallExpr>(E)) {
+ if (C->getSourceRange() == SR)
+ return true;
+ }
+
+ if (const auto *C = dyn_cast<MemberExpr>(E)) {
+ if (C->getSourceRange() == SR)
+ return true;
+ }
+ return false;
+ };
+
+ while (ShouldSkip(E, Child)) {
+ auto It = PointerParents.find(E);
+ if (It == PointerParents.end())
+ break;
+ const auto *S = It->second.dyn_cast<const Stmt *>();
+ if (!S) {
+ if (auto *Vec = It->second.dyn_cast<ParentVector *>())
+ return llvm::makeArrayRef(*Vec);
+ return getSingleDynTypedNodeFromParentMap(It->second);
+ }
+ const auto *P = dyn_cast<Expr>(S);
+ if (!P)
+ return DynTypedNode::create(*S);
+ Child = E;
+ E = P;
+ }
+ return DynTypedNode::create(*E);
+ }
+};
+
+/// Template specializations to abstract away from pointers and TypeLocs.
+/// @{
+template <typename T> static DynTypedNode createDynTypedNode(const T &Node) {
+ return DynTypedNode::create(*Node);
+}
+template <> DynTypedNode createDynTypedNode(const TypeLoc &Node) {
+ return DynTypedNode::create(Node);
+}
+template <>
+DynTypedNode createDynTypedNode(const NestedNameSpecifierLoc &Node) {
+ return DynTypedNode::create(Node);
+}
+/// @}
+
+/// A \c RecursiveASTVisitor that builds a map from nodes to their
+/// parents as defined by the \c RecursiveASTVisitor.
+///
+/// Note that the relationship described here is purely in terms of AST
+/// traversal - there are other relationships (for example declaration context)
+/// in the AST that are better modeled by special matchers.
+///
+/// FIXME: Currently only builds up the map using \c Stmt and \c Decl nodes.
+class ParentMapContext::ParentMap::ASTVisitor
+ : public RecursiveASTVisitor<ASTVisitor> {
+public:
+ ASTVisitor(ParentMap &Map) : Map(Map) {}
+
+private:
+ friend class RecursiveASTVisitor<ASTVisitor>;
+
+ using VisitorBase = RecursiveASTVisitor<ASTVisitor>;
+
+ bool shouldVisitTemplateInstantiations() const { return true; }
+
+ bool shouldVisitImplicitCode() const { return true; }
+
+ template <typename T, typename MapNodeTy, typename BaseTraverseFn,
+ typename MapTy>
+ bool TraverseNode(T Node, MapNodeTy MapNode, BaseTraverseFn BaseTraverse,
+ MapTy *Parents) {
+ if (!Node)
+ return true;
+ if (ParentStack.size() > 0) {
+ // FIXME: Currently we add the same parent multiple times, but only
+ // when no memoization data is available for the type.
+ // For example when we visit all subexpressions of template
+ // instantiations; this is suboptimal, but benign: the only way to
+ // visit those is with hasAncestor / hasParent, and those do not create
+ // new matches.
+ // The plan is to enable DynTypedNode to be storable in a map or hash
+ // map. The main problem there is to implement hash functions /
+ // comparison operators for all types that DynTypedNode supports that
+ // do not have pointer identity.
+ auto &NodeOrVector = (*Parents)[MapNode];
+ if (NodeOrVector.isNull()) {
+ if (const auto *D = ParentStack.back().get<Decl>())
+ NodeOrVector = D;
+ else if (const auto *S = ParentStack.back().get<Stmt>())
+ NodeOrVector = S;
+ else
+ NodeOrVector = new DynTypedNode(ParentStack.back());
+ } else {
+ if (!NodeOrVector.template is<ParentVector *>()) {
+ auto *Vector = new ParentVector(
+ 1, getSingleDynTypedNodeFromParentMap(NodeOrVector));
+ delete NodeOrVector.template dyn_cast<DynTypedNode *>();
+ NodeOrVector = Vector;
+ }
+
+ auto *Vector = NodeOrVector.template get<ParentVector *>();
+ // Skip duplicates for types that have memoization data.
+ // We must check that the type has memoization data before calling
+ // std::find() because DynTypedNode::operator== can't compare all
+ // types.
+ bool Found = ParentStack.back().getMemoizationData() &&
+ std::find(Vector->begin(), Vector->end(),
+ ParentStack.back()) != Vector->end();
+ if (!Found)
+ Vector->push_back(ParentStack.back());
+ }
+ }
+ ParentStack.push_back(createDynTypedNode(Node));
+ bool Result = BaseTraverse();
+ ParentStack.pop_back();
+ return Result;
+ }
+
+ bool TraverseDecl(Decl *DeclNode) {
+ return TraverseNode(
+ DeclNode, DeclNode, [&] { return VisitorBase::TraverseDecl(DeclNode); },
+ &Map.PointerParents);
+ }
+
+ bool TraverseStmt(Stmt *StmtNode) {
+ return TraverseNode(StmtNode, StmtNode,
+ [&] { return VisitorBase::TraverseStmt(StmtNode); },
+ &Map.PointerParents);
+ }
+
+ bool TraverseTypeLoc(TypeLoc TypeLocNode) {
+ return TraverseNode(
+ TypeLocNode, DynTypedNode::create(TypeLocNode),
+ [&] { return VisitorBase::TraverseTypeLoc(TypeLocNode); },
+ &Map.OtherParents);
+ }
+
+ bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) {
+ return TraverseNode(
+ NNSLocNode, DynTypedNode::create(NNSLocNode),
+ [&] { return VisitorBase::TraverseNestedNameSpecifierLoc(NNSLocNode); },
+ &Map.OtherParents);
+ }
+
+ ParentMap &Map;
+ llvm::SmallVector<DynTypedNode, 16> ParentStack;
+};
+
+ParentMapContext::ParentMap::ParentMap(ASTContext &Ctx) {
+ ASTVisitor(*this).TraverseAST(Ctx);
+}
+
+DynTypedNodeList ParentMapContext::getParents(const DynTypedNode &Node) {
+ if (!Parents)
+ // We build the parent map for the traversal scope (usually whole TU), as
+ // hasAncestor can escape any subtree.
+ Parents = std::make_unique<ParentMap>(ASTCtx);
+ return Parents->getParents(getTraversalKind(), Node);
+}
diff --git a/clang/lib/AST/PrintfFormatString.cpp b/clang/lib/AST/PrintfFormatString.cpp
index bae60d4644078..f3ac181214ac6 100644
--- a/clang/lib/AST/PrintfFormatString.cpp
+++ b/clang/lib/AST/PrintfFormatString.cpp
@@ -11,10 +11,11 @@
//
//===----------------------------------------------------------------------===//
+#include "FormatStringParsing.h"
#include "clang/AST/FormatString.h"
#include "clang/AST/OSLog.h"
-#include "FormatStringParsing.h"
#include "clang/Basic/TargetInfo.h"
+#include "llvm/Support/Regex.h"
using clang::analyze_format_string::ArgType;
using clang::analyze_format_string::FormatStringHandler;
@@ -751,6 +752,7 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
case BuiltinType::UInt128:
case BuiltinType::Int128:
case BuiltinType::Half:
+ case BuiltinType::BFloat16:
case BuiltinType::Float16:
case BuiltinType::Float128:
case BuiltinType::ShortAccum:
diff --git a/clang/lib/AST/RawCommentList.cpp b/clang/lib/AST/RawCommentList.cpp
index 83e8a0b942a40..a8d15036cab99 100644
--- a/clang/lib/AST/RawCommentList.cpp
+++ b/clang/lib/AST/RawCommentList.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/CommentSema.h"
#include "clang/Basic/CharInfo.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Allocator.h"
using namespace clang;
@@ -430,7 +431,7 @@ std::string RawComment::getFormattedText(const SourceManager &SourceMgr,
};
auto DropTrailingNewLines = [](std::string &Str) {
- while (Str.back() == '\n')
+ while (!Str.empty() && Str.back() == '\n')
Str.pop_back();
};
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index 9a21732b63e3f..d56c7e2ab8c0e 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/VTableBuilder.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/Support/Format.h"
@@ -1186,11 +1187,10 @@ ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
// Query the external layout to see if it provides an offset.
bool HasExternalLayout = false;
if (UseExternalLayout) {
- // FIXME: This appears to be reversed.
if (Base->IsVirtual)
- HasExternalLayout = External.getExternalNVBaseOffset(Base->Class, Offset);
- else
HasExternalLayout = External.getExternalVBaseOffset(Base->Class, Offset);
+ else
+ HasExternalLayout = External.getExternalNVBaseOffset(Base->Class, Offset);
}
// Clang <= 6 incorrectly applied the 'packed' attribute to base classes.
@@ -2107,7 +2107,7 @@ static const CXXMethodDecl *computeKeyFunction(ASTContext &Context,
if (MD->isImplicit())
continue;
- if (MD->isInlineSpecified())
+ if (MD->isInlineSpecified() || MD->isConstexpr())
continue;
if (MD->hasInlineBody())
@@ -2568,9 +2568,11 @@ MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl *RD) {
// information about the bases, such as required alignment and the presence of
// zero sized members.
const ASTRecordLayout *PreviousBaseLayout = nullptr;
+ bool HasPolymorphicBaseClass = false;
// Iterate through the bases and lay out the non-virtual ones.
for (const CXXBaseSpecifier &Base : RD->bases()) {
const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
+ HasPolymorphicBaseClass |= BaseDecl->isPolymorphic();
const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl);
// Mark and skip virtual bases.
if (Base.isVirtual()) {
@@ -2594,11 +2596,23 @@ MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl *RD) {
layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
}
// Figure out if we need a fresh VFPtr for this class.
- if (!PrimaryBase && RD->isDynamicClass())
- for (CXXRecordDecl::method_iterator i = RD->method_begin(),
- e = RD->method_end();
- !HasOwnVFPtr && i != e; ++i)
- HasOwnVFPtr = i->isVirtual() && i->size_overridden_methods() == 0;
+ if (RD->isPolymorphic()) {
+ if (!HasPolymorphicBaseClass)
+ // This class introduces polymorphism, so we need a vftable to store the
+ // RTTI information.
+ HasOwnVFPtr = true;
+ else if (!PrimaryBase) {
+ // We have a polymorphic base class but can't extend its vftable. Add a
+ // new vfptr if we would use any vftable slots.
+ for (CXXMethodDecl *M : RD->methods()) {
+ if (MicrosoftVTableContext::hasVtableSlot(M) &&
+ M->size_overridden_methods() == 0) {
+ HasOwnVFPtr = true;
+ break;
+ }
+ }
+ }
+ }
// If we don't have a primary base then we have a leading object that could
// itself lead with a zero-sized object, something we track.
bool CheckLeadingLayout = !PrimaryBase;
@@ -2993,7 +3007,8 @@ void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
llvm::SmallPtrSet<const CXXRecordDecl *, 2> BasesWithOverriddenMethods;
// Seed the working set with our non-destructor, non-pure virtual methods.
for (const CXXMethodDecl *MD : RD->methods())
- if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD) && !MD->isPure())
+ if (MicrosoftVTableContext::hasVtableSlot(MD) &&
+ !isa<CXXDestructorDecl>(MD) && !MD->isPure())
Work.insert(MD);
while (!Work.empty()) {
const CXXMethodDecl *MD = *Work.begin();
@@ -3222,7 +3237,8 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
if (D->hasExternalLexicalStorage() && !D->getDefinition())
getExternalSource()->CompleteType(const_cast<ObjCInterfaceDecl*>(D));
D = D->getDefinition();
- assert(D && D->isThisDeclarationADefinition() && "Invalid interface decl!");
+ assert(D && !D->isInvalidDecl() && D->isThisDeclarationADefinition() &&
+ "Invalid interface decl!");
// Look up this layout, if already laid out, return what we have.
const ObjCContainerDecl *Key =
diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp
index b6e4d8aff21e9..25e685be3e9b1 100644
--- a/clang/lib/AST/Stmt.cpp
+++ b/clang/lib/AST/Stmt.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclGroup.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprConcepts.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprOpenMP.h"
@@ -272,7 +273,6 @@ SourceRange Stmt::getSourceRange() const {
}
SourceLocation Stmt::getBeginLoc() const {
- // llvm::errs() << "getBeginLoc() for " << getStmtClassName() << "\n";
switch (getStmtClass()) {
case Stmt::NoStmtClass: llvm_unreachable("statement without class");
#define ABSTRACT_STMT(type)
@@ -456,7 +456,7 @@ void GCCAsmStmt::setInputExpr(unsigned i, Expr *E) {
}
AddrLabelExpr *GCCAsmStmt::getLabelExpr(unsigned i) const {
- return cast<AddrLabelExpr>(Exprs[i + NumInputs]);
+ return cast<AddrLabelExpr>(Exprs[i + NumOutputs + NumInputs]);
}
StringRef GCCAsmStmt::getLabelName(unsigned i) const {
@@ -522,7 +522,7 @@ int GCCAsmStmt::getNamedOperand(StringRef SymbolicName) const {
for (unsigned i = 0, e = getNumLabels(); i != e; ++i)
if (getLabelName(i) == SymbolicName)
- return i + getNumInputs();
+ return i + getNumOutputs() + getNumInputs();
// Not found.
return -1;
@@ -731,7 +731,7 @@ std::string GCCAsmStmt::generateAsmString(const ASTContext &C) const {
/// Assemble final IR asm string (MS-style).
std::string MSAsmStmt::generateAsmString(const ASTContext &C) const {
// FIXME: This needs to be translated into the IR string representation.
- return AsmStr;
+ return std::string(AsmStr);
}
Expr *MSAsmStmt::getOutputExpr(unsigned i) {
@@ -1012,7 +1012,8 @@ void SwitchStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) {
}
WhileStmt::WhileStmt(const ASTContext &Ctx, VarDecl *Var, Expr *Cond,
- Stmt *Body, SourceLocation WL)
+ Stmt *Body, SourceLocation WL, SourceLocation LParenLoc,
+ SourceLocation RParenLoc)
: Stmt(WhileStmtClass) {
bool HasVar = Var != nullptr;
WhileStmtBits.HasVar = HasVar;
@@ -1023,6 +1024,8 @@ WhileStmt::WhileStmt(const ASTContext &Ctx, VarDecl *Var, Expr *Cond,
setConditionVariable(Ctx, Var);
setWhileLoc(WL);
+ setLParenLoc(LParenLoc);
+ setRParenLoc(RParenLoc);
}
WhileStmt::WhileStmt(EmptyShell Empty, bool HasVar)
@@ -1031,12 +1034,14 @@ WhileStmt::WhileStmt(EmptyShell Empty, bool HasVar)
}
WhileStmt *WhileStmt::Create(const ASTContext &Ctx, VarDecl *Var, Expr *Cond,
- Stmt *Body, SourceLocation WL) {
+ Stmt *Body, SourceLocation WL,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc) {
bool HasVar = Var != nullptr;
void *Mem =
Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar),
alignof(WhileStmt));
- return new (Mem) WhileStmt(Ctx, Var, Cond, Body, WL);
+ return new (Mem) WhileStmt(Ctx, Var, Cond, Body, WL, LParenLoc, RParenLoc);
}
WhileStmt *WhileStmt::CreateEmpty(const ASTContext &Ctx, bool HasVar) {
diff --git a/clang/lib/AST/StmtOpenMP.cpp b/clang/lib/AST/StmtOpenMP.cpp
index da6d308ad15bf..788fac789270f 100644
--- a/clang/lib/AST/StmtOpenMP.cpp
+++ b/clang/lib/AST/StmtOpenMP.cpp
@@ -10,9 +10,8 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/StmtOpenMP.h"
-
#include "clang/AST/ASTContext.h"
+#include "clang/AST/StmtOpenMP.h"
using namespace clang;
using namespace llvm::omp;
@@ -162,7 +161,8 @@ void OMPLoopDirective::setFinalsConditions(ArrayRef<Expr *> A) {
OMPParallelDirective *OMPParallelDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) {
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
+ bool HasCancel) {
unsigned Size =
llvm::alignTo(sizeof(OMPParallelDirective), alignof(OMPClause *));
void *Mem =
@@ -171,6 +171,7 @@ OMPParallelDirective *OMPParallelDirective::Create(
new (Mem) OMPParallelDirective(StartLoc, EndLoc, Clauses.size());
Dir->setClauses(Clauses);
Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setTaskReductionRefExpr(TaskRedRef);
Dir->setHasCancel(HasCancel);
return Dir;
}
@@ -228,11 +229,10 @@ OMPSimdDirective *OMPSimdDirective::CreateEmpty(const ASTContext &C,
return new (Mem) OMPSimdDirective(CollapsedNum, NumClauses);
}
-OMPForDirective *
-OMPForDirective::Create(const ASTContext &C, SourceLocation StartLoc,
- SourceLocation EndLoc, unsigned CollapsedNum,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
- const HelperExprs &Exprs, bool HasCancel) {
+OMPForDirective *OMPForDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel) {
unsigned Size = llvm::alignTo(sizeof(OMPForDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
@@ -265,6 +265,7 @@ OMPForDirective::Create(const ASTContext &C, SourceLocation StartLoc,
Dir->setDependentInits(Exprs.DependentInits);
Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
+ Dir->setTaskReductionRefExpr(TaskRedRef);
Dir->setHasCancel(HasCancel);
return Dir;
}
@@ -335,7 +336,8 @@ OMPForSimdDirective *OMPForSimdDirective::CreateEmpty(const ASTContext &C,
OMPSectionsDirective *OMPSectionsDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) {
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
+ bool HasCancel) {
unsigned Size =
llvm::alignTo(sizeof(OMPSectionsDirective), alignof(OMPClause *));
void *Mem =
@@ -344,6 +346,7 @@ OMPSectionsDirective *OMPSectionsDirective::Create(
new (Mem) OMPSectionsDirective(StartLoc, EndLoc, Clauses.size());
Dir->setClauses(Clauses);
Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setTaskReductionRefExpr(TaskRedRef);
Dir->setHasCancel(HasCancel);
return Dir;
}
@@ -450,7 +453,7 @@ OMPCriticalDirective *OMPCriticalDirective::CreateEmpty(const ASTContext &C,
OMPParallelForDirective *OMPParallelForDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
- const HelperExprs &Exprs, bool HasCancel) {
+ const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel) {
unsigned Size =
llvm::alignTo(sizeof(OMPParallelForDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
@@ -484,6 +487,7 @@ OMPParallelForDirective *OMPParallelForDirective::Create(
Dir->setDependentInits(Exprs.DependentInits);
Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
+ Dir->setTaskReductionRefExpr(TaskRedRef);
Dir->setHasCancel(HasCancel);
return Dir;
}
@@ -553,7 +557,7 @@ OMPParallelForSimdDirective::CreateEmpty(const ASTContext &C,
OMPParallelMasterDirective *OMPParallelMasterDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef) {
unsigned Size =
llvm::alignTo(sizeof(OMPParallelMasterDirective), alignof(OMPClause *));
void *Mem =
@@ -562,6 +566,7 @@ OMPParallelMasterDirective *OMPParallelMasterDirective::Create(
new (Mem) OMPParallelMasterDirective(StartLoc, EndLoc, Clauses.size());
Dir->setClauses(Clauses);
Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setTaskReductionRefExpr(TaskRedRef);
return Dir;
}
@@ -577,7 +582,8 @@ OMPParallelMasterDirective *OMPParallelMasterDirective::CreateEmpty(const ASTCon
OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) {
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
+ bool HasCancel) {
unsigned Size =
llvm::alignTo(sizeof(OMPParallelSectionsDirective), alignof(OMPClause *));
void *Mem =
@@ -586,6 +592,7 @@ OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create(
new (Mem) OMPParallelSectionsDirective(StartLoc, EndLoc, Clauses.size());
Dir->setClauses(Clauses);
Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setTaskReductionRefExpr(TaskRedRef);
Dir->setHasCancel(HasCancel);
return Dir;
}
@@ -759,6 +766,50 @@ OMPFlushDirective *OMPFlushDirective::CreateEmpty(const ASTContext &C,
return new (Mem) OMPFlushDirective(NumClauses);
}
+OMPDepobjDirective *OMPDepobjDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses) {
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPDepobjDirective), alignof(OMPClause *));
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size(),
+ alignof(OMPDepobjDirective));
+ auto *Dir = new (Mem) OMPDepobjDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ return Dir;
+}
+
+OMPDepobjDirective *OMPDepobjDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPDepobjDirective), alignof(OMPClause *));
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses,
+ alignof(OMPDepobjDirective));
+ return new (Mem) OMPDepobjDirective(NumClauses);
+}
+
+OMPScanDirective *OMPScanDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses) {
+ unsigned Size = llvm::alignTo(sizeof(OMPScanDirective), alignof(OMPClause *));
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size(),
+ alignof(OMPScanDirective));
+ auto *Dir = new (Mem) OMPScanDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ return Dir;
+}
+
+OMPScanDirective *OMPScanDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ unsigned Size = llvm::alignTo(sizeof(OMPScanDirective), alignof(OMPClause *));
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses,
+ alignof(OMPScanDirective));
+ return new (Mem) OMPScanDirective(NumClauses);
+}
+
OMPOrderedDirective *OMPOrderedDirective::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc,
@@ -844,7 +895,8 @@ OMPTargetDirective *OMPTargetDirective::CreateEmpty(const ASTContext &C,
OMPTargetParallelDirective *OMPTargetParallelDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
+ bool HasCancel) {
unsigned Size =
llvm::alignTo(sizeof(OMPTargetParallelDirective), alignof(OMPClause *));
void *Mem =
@@ -853,6 +905,8 @@ OMPTargetParallelDirective *OMPTargetParallelDirective::Create(
new (Mem) OMPTargetParallelDirective(StartLoc, EndLoc, Clauses.size());
Dir->setClauses(Clauses);
Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setTaskReductionRefExpr(TaskRedRef);
+ Dir->setHasCancel(HasCancel);
return Dir;
}
@@ -869,7 +923,7 @@ OMPTargetParallelDirective::CreateEmpty(const ASTContext &C,
OMPTargetParallelForDirective *OMPTargetParallelForDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
- const HelperExprs &Exprs, bool HasCancel) {
+ const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel) {
unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForDirective),
alignof(OMPClause *));
void *Mem = C.Allocate(
@@ -903,6 +957,7 @@ OMPTargetParallelForDirective *OMPTargetParallelForDirective::Create(
Dir->setDependentInits(Exprs.DependentInits);
Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
+ Dir->setTaskReductionRefExpr(TaskRedRef);
Dir->setHasCancel(HasCancel);
return Dir;
}
@@ -1014,7 +1069,7 @@ OMPTeamsDirective *OMPTeamsDirective::CreateEmpty(const ASTContext &C,
OMPTaskLoopDirective *OMPTaskLoopDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
- const HelperExprs &Exprs) {
+ const HelperExprs &Exprs, bool HasCancel) {
unsigned Size =
llvm::alignTo(sizeof(OMPTaskLoopDirective), alignof(OMPClause *));
void *Mem =
@@ -1048,6 +1103,7 @@ OMPTaskLoopDirective *OMPTaskLoopDirective::Create(
Dir->setDependentInits(Exprs.DependentInits);
Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
+ Dir->setHasCancel(HasCancel);
return Dir;
}
@@ -1117,7 +1173,7 @@ OMPTaskLoopSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
OMPMasterTaskLoopDirective *OMPMasterTaskLoopDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
- const HelperExprs &Exprs) {
+ const HelperExprs &Exprs, bool HasCancel) {
unsigned Size =
llvm::alignTo(sizeof(OMPMasterTaskLoopDirective), alignof(OMPClause *));
void *Mem = C.Allocate(
@@ -1151,6 +1207,7 @@ OMPMasterTaskLoopDirective *OMPMasterTaskLoopDirective::Create(
Dir->setDependentInits(Exprs.DependentInits);
Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
+ Dir->setHasCancel(HasCancel);
return Dir;
}
@@ -1223,7 +1280,7 @@ OMPMasterTaskLoopSimdDirective::CreateEmpty(const ASTContext &C,
OMPParallelMasterTaskLoopDirective *OMPParallelMasterTaskLoopDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
- const HelperExprs &Exprs) {
+ const HelperExprs &Exprs, bool HasCancel) {
unsigned Size = llvm::alignTo(sizeof(OMPParallelMasterTaskLoopDirective),
alignof(OMPClause *));
void *Mem = C.Allocate(
@@ -1258,6 +1315,7 @@ OMPParallelMasterTaskLoopDirective *OMPParallelMasterTaskLoopDirective::Create(
Dir->setDependentInits(Exprs.DependentInits);
Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
+ Dir->setHasCancel(HasCancel);
return Dir;
}
@@ -1410,7 +1468,7 @@ OMPTargetUpdateDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
OMPDistributeParallelForDirective *OMPDistributeParallelForDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
- const HelperExprs &Exprs, bool HasCancel) {
+ const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel) {
unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForDirective),
alignof(OMPClause *));
void *Mem = C.Allocate(
@@ -1459,6 +1517,7 @@ OMPDistributeParallelForDirective *OMPDistributeParallelForDirective::Create(
Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB);
Dir->setCombinedDistCond(Exprs.DistCombinedFields.DistCond);
Dir->setCombinedParForInDistCond(Exprs.DistCombinedFields.ParForInDistCond);
+ Dir->setTaskReductionRefExpr(TaskRedRef);
Dir->HasCancel = HasCancel;
return Dir;
}
@@ -1885,7 +1944,7 @@ OMPTeamsDistributeParallelForDirective *
OMPTeamsDistributeParallelForDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
- const HelperExprs &Exprs, bool HasCancel) {
+ const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel) {
auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForDirective),
alignof(OMPClause *));
void *Mem = C.Allocate(
@@ -1934,6 +1993,7 @@ OMPTeamsDistributeParallelForDirective::Create(
Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB);
Dir->setCombinedDistCond(Exprs.DistCombinedFields.DistCond);
Dir->setCombinedParForInDistCond(Exprs.DistCombinedFields.ParForInDistCond);
+ Dir->setTaskReductionRefExpr(TaskRedRef);
Dir->HasCancel = HasCancel;
return Dir;
}
@@ -2037,7 +2097,7 @@ OMPTargetTeamsDistributeParallelForDirective *
OMPTargetTeamsDistributeParallelForDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
- const HelperExprs &Exprs, bool HasCancel) {
+ const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel) {
auto Size =
llvm::alignTo(sizeof(OMPTargetTeamsDistributeParallelForDirective),
alignof(OMPClause *));
@@ -2088,6 +2148,7 @@ OMPTargetTeamsDistributeParallelForDirective::Create(
Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB);
Dir->setCombinedDistCond(Exprs.DistCombinedFields.DistCond);
Dir->setCombinedParForInDistCond(Exprs.DistCombinedFields.ParForInDistCond);
+ Dir->setTaskReductionRefExpr(TaskRedRef);
Dir->HasCancel = HasCancel;
return Dir;
}
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index c14bb886bb11a..f797f5fe8e6d1 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -75,14 +75,11 @@ namespace {
public:
StmtPrinter(raw_ostream &os, PrinterHelper *helper,
const PrintingPolicy &Policy, unsigned Indentation = 0,
- StringRef NL = "\n",
- const ASTContext *Context = nullptr)
+ StringRef NL = "\n", const ASTContext *Context = nullptr)
: OS(os), IndentLevel(Indentation), Helper(helper), Policy(Policy),
NL(NL), Context(Context) {}
- void PrintStmt(Stmt *S) {
- PrintStmt(S, Policy.Indentation);
- }
+ void PrintStmt(Stmt *S) { PrintStmt(S, Policy.Indentation); }
void PrintStmt(Stmt *S, int SubIndent) {
IndentLevel += SubIndent;
@@ -756,6 +753,16 @@ void StmtPrinter::VisitOMPFlushDirective(OMPFlushDirective *Node) {
PrintOMPExecutableDirective(Node);
}
+void StmtPrinter::VisitOMPDepobjDirective(OMPDepobjDirective *Node) {
+ Indent() << "#pragma omp depobj";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPScanDirective(OMPScanDirective *Node) {
+ Indent() << "#pragma omp scan";
+ PrintOMPExecutableDirective(Node);
+}
+
void StmtPrinter::VisitOMPOrderedDirective(OMPOrderedDirective *Node) {
Indent() << "#pragma omp ordered";
PrintOMPExecutableDirective(Node, Node->hasClausesOfKind<OMPDependClause>());
@@ -1274,29 +1281,20 @@ void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) {
OS << ")";
}
-void StmtPrinter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node){
- switch(Node->getKind()) {
- case UETT_SizeOf:
- OS << "sizeof";
- break;
- case UETT_AlignOf:
+void StmtPrinter::VisitUnaryExprOrTypeTraitExpr(
+ UnaryExprOrTypeTraitExpr *Node) {
+ const char *Spelling = getTraitSpelling(Node->getKind());
+ if (Node->getKind() == UETT_AlignOf) {
if (Policy.Alignof)
- OS << "alignof";
+ Spelling = "alignof";
else if (Policy.UnderscoreAlignof)
- OS << "_Alignof";
+ Spelling = "_Alignof";
else
- OS << "__alignof";
- break;
- case UETT_PreferredAlignOf:
- OS << "__alignof";
- break;
- case UETT_VecStep:
- OS << "vec_step";
- break;
- case UETT_OpenMPRequiredSimdAlign:
- OS << "__builtin_omp_required_simd_align";
- break;
+ Spelling = "__alignof";
}
+
+ OS << Spelling;
+
if (Node->isArgumentType()) {
OS << '(';
Node->getArgumentType().print(OS, Policy);
@@ -1330,19 +1328,65 @@ void StmtPrinter::VisitArraySubscriptExpr(ArraySubscriptExpr *Node) {
OS << "]";
}
+void StmtPrinter::VisitMatrixSubscriptExpr(MatrixSubscriptExpr *Node) {
+ PrintExpr(Node->getBase());
+ OS << "[";
+ PrintExpr(Node->getRowIdx());
+ OS << "]";
+ OS << "[";
+ PrintExpr(Node->getColumnIdx());
+ OS << "]";
+}
+
void StmtPrinter::VisitOMPArraySectionExpr(OMPArraySectionExpr *Node) {
PrintExpr(Node->getBase());
OS << "[";
if (Node->getLowerBound())
PrintExpr(Node->getLowerBound());
- if (Node->getColonLoc().isValid()) {
+ if (Node->getColonLocFirst().isValid()) {
OS << ":";
if (Node->getLength())
PrintExpr(Node->getLength());
}
+ if (Node->getColonLocSecond().isValid()) {
+ OS << ":";
+ if (Node->getStride())
+ PrintExpr(Node->getStride());
+ }
OS << "]";
}
+void StmtPrinter::VisitOMPArrayShapingExpr(OMPArrayShapingExpr *Node) {
+ OS << "(";
+ for (Expr *E : Node->getDimensions()) {
+ OS << "[";
+ PrintExpr(E);
+ OS << "]";
+ }
+ OS << ")";
+ PrintExpr(Node->getBase());
+}
+
+void StmtPrinter::VisitOMPIteratorExpr(OMPIteratorExpr *Node) {
+ OS << "iterator(";
+ for (unsigned I = 0, E = Node->numOfIterators(); I < E; ++I) {
+ auto *VD = cast<ValueDecl>(Node->getIteratorDecl(I));
+ VD->getType().print(OS, Policy);
+ const OMPIteratorExpr::IteratorRange Range = Node->getIteratorRange(I);
+ OS << " " << VD->getName() << " = ";
+ PrintExpr(Range.Begin);
+ OS << ":";
+ PrintExpr(Range.End);
+ if (Range.Step) {
+ OS << ":";
+ PrintExpr(Range.Step);
+ }
+ if (I < E - 1)
+ OS << ", ";
+ }
+ OS << ")";
+}
+
void StmtPrinter::PrintCallArgs(CallExpr *Call) {
for (unsigned i = 0, e = Call->getNumArgs(); i != e; ++i) {
if (isa<CXXDefaultArgExpr>(Call->getArg(i))) {
@@ -1750,6 +1794,10 @@ void StmtPrinter::VisitBuiltinBitCastExpr(BuiltinBitCastExpr *Node) {
OS << ")";
}
+void StmtPrinter::VisitCXXAddrspaceCastExpr(CXXAddrspaceCastExpr *Node) {
+ VisitCXXNamedCastExpr(Node);
+}
+
void StmtPrinter::VisitCXXTypeidExpr(CXXTypeidExpr *Node) {
OS << "typeid(";
if (Node->isTypeOperand()) {
@@ -2008,7 +2056,7 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
if (Policy.TerseOutput)
OS << "{}";
else
- PrintRawCompoundStmt(Node->getBody());
+ PrintRawCompoundStmt(Node->getCompoundStmtBody());
}
void StmtPrinter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *Node) {
@@ -2160,37 +2208,8 @@ void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) {
printTemplateArgumentList(OS, Node->template_arguments(), Policy);
}
-static const char *getTypeTraitName(TypeTrait TT) {
- switch (TT) {
-#define TYPE_TRAIT_1(Spelling, Name, Key) \
-case clang::UTT_##Name: return #Spelling;
-#define TYPE_TRAIT_2(Spelling, Name, Key) \
-case clang::BTT_##Name: return #Spelling;
-#define TYPE_TRAIT_N(Spelling, Name, Key) \
- case clang::TT_##Name: return #Spelling;
-#include "clang/Basic/TokenKinds.def"
- }
- llvm_unreachable("Type trait not covered by switch");
-}
-
-static const char *getTypeTraitName(ArrayTypeTrait ATT) {
- switch (ATT) {
- case ATT_ArrayRank: return "__array_rank";
- case ATT_ArrayExtent: return "__array_extent";
- }
- llvm_unreachable("Array type trait not covered by switch");
-}
-
-static const char *getExpressionTraitName(ExpressionTrait ET) {
- switch (ET) {
- case ET_IsLValueExpr: return "__is_lvalue_expr";
- case ET_IsRValueExpr: return "__is_rvalue_expr";
- }
- llvm_unreachable("Expression type trait not covered by switch");
-}
-
void StmtPrinter::VisitTypeTraitExpr(TypeTraitExpr *E) {
- OS << getTypeTraitName(E->getTrait()) << "(";
+ OS << getTraitSpelling(E->getTrait()) << "(";
for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) {
if (I > 0)
OS << ", ";
@@ -2200,13 +2219,13 @@ void StmtPrinter::VisitTypeTraitExpr(TypeTraitExpr *E) {
}
void StmtPrinter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
- OS << getTypeTraitName(E->getTrait()) << '(';
+ OS << getTraitSpelling(E->getTrait()) << '(';
E->getQueriedType().print(OS, Policy);
OS << ')';
}
void StmtPrinter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
- OS << getExpressionTraitName(E->getTrait()) << '(';
+ OS << getTraitSpelling(E->getTrait()) << '(';
PrintExpr(E->getQueriedExpression());
OS << ')';
}
@@ -2269,6 +2288,60 @@ void StmtPrinter::VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) {
Policy);
}
+void StmtPrinter::VisitRequiresExpr(RequiresExpr *E) {
+ OS << "requires ";
+ auto LocalParameters = E->getLocalParameters();
+ if (!LocalParameters.empty()) {
+ OS << "(";
+ for (ParmVarDecl *LocalParam : LocalParameters) {
+ PrintRawDecl(LocalParam);
+ if (LocalParam != LocalParameters.back())
+ OS << ", ";
+ }
+
+ OS << ") ";
+ }
+ OS << "{ ";
+ auto Requirements = E->getRequirements();
+ for (concepts::Requirement *Req : Requirements) {
+ if (auto *TypeReq = dyn_cast<concepts::TypeRequirement>(Req)) {
+ if (TypeReq->isSubstitutionFailure())
+ OS << "<<error-type>>";
+ else
+ TypeReq->getType()->getType().print(OS, Policy);
+ } else if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(Req)) {
+ if (ExprReq->isCompound())
+ OS << "{ ";
+ if (ExprReq->isExprSubstitutionFailure())
+ OS << "<<error-expression>>";
+ else
+ PrintExpr(ExprReq->getExpr());
+ if (ExprReq->isCompound()) {
+ OS << " }";
+ if (ExprReq->getNoexceptLoc().isValid())
+ OS << " noexcept";
+ const auto &RetReq = ExprReq->getReturnTypeRequirement();
+ if (!RetReq.isEmpty()) {
+ OS << " -> ";
+ if (RetReq.isSubstitutionFailure())
+ OS << "<<error-type>>";
+ else if (RetReq.isTypeConstraint())
+ RetReq.getTypeConstraint()->print(OS, Policy);
+ }
+ }
+ } else {
+ auto *NestedReq = cast<concepts::NestedRequirement>(Req);
+ OS << "requires ";
+ if (NestedReq->isSubstitutionFailure())
+ OS << "<<error-expression>>";
+ else
+ PrintExpr(NestedReq->getConstraintExpr());
+ }
+ OS << "; ";
+ }
+ OS << "}";
+}
+
// C++ Coroutines TS
void StmtPrinter::VisitCoroutineBodyStmt(CoroutineBodyStmt *S) {
@@ -2445,6 +2518,17 @@ void StmtPrinter::VisitTypoExpr(TypoExpr *Node) {
llvm_unreachable("Cannot print TypoExpr nodes");
}
+void StmtPrinter::VisitRecoveryExpr(RecoveryExpr *Node) {
+ OS << "<recovery-expr>(";
+ const char *Sep = "";
+ for (Expr *E : Node->subExpressions()) {
+ OS << Sep;
+ PrintExpr(E);
+ Sep = ", ";
+ }
+ OS << ')';
+}
+
void StmtPrinter::VisitAsTypeExpr(AsTypeExpr *Node) {
OS << "__builtin_astype(";
PrintExpr(Node->getSrcExpr());
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 2aa5106e90fae..bf3b43b816f17 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/ODRHash.h"
+#include "clang/AST/OpenMPClause.h"
#include "clang/AST/StmtVisitor.h"
#include "llvm/ADT/FoldingSet.h"
using namespace clang;
@@ -413,9 +414,8 @@ class OMPClauseProfiler : public ConstOMPClauseVisitor<OMPClauseProfiler> {
public:
OMPClauseProfiler(StmtProfiler *P) : Profiler(P) { }
-#define OPENMP_CLAUSE(Name, Class) \
- void Visit##Class(const Class *C);
-#include "clang/Basic/OpenMPKinds.def"
+#define OMP_CLAUSE_CLASS(Enum, Str, Class) void Visit##Class(const Class *C);
+#include "llvm/Frontend/OpenMP/OMPKinds.def"
void VistOMPClauseWithPreInit(const OMPClauseWithPreInit *C);
void VistOMPClauseWithPostUpdate(const OMPClauseWithPostUpdate *C);
};
@@ -471,6 +471,11 @@ void OMPClauseProfiler::VisitOMPCollapseClause(const OMPCollapseClause *C) {
Profiler->VisitStmt(C->getNumForLoops());
}
+void OMPClauseProfiler::VisitOMPDetachClause(const OMPDetachClause *C) {
+ if (Expr *Evt = C->getEventHandler())
+ Profiler->VisitStmt(Evt);
+}
+
void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
void OMPClauseProfiler::VisitOMPProcBindClause(const OMPProcBindClause *C) { }
@@ -517,12 +522,22 @@ void OMPClauseProfiler::VisitOMPCaptureClause(const OMPCaptureClause *) {}
void OMPClauseProfiler::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
+void OMPClauseProfiler::VisitOMPAcqRelClause(const OMPAcqRelClause *) {}
+
+void OMPClauseProfiler::VisitOMPAcquireClause(const OMPAcquireClause *) {}
+
+void OMPClauseProfiler::VisitOMPReleaseClause(const OMPReleaseClause *) {}
+
+void OMPClauseProfiler::VisitOMPRelaxedClause(const OMPRelaxedClause *) {}
+
void OMPClauseProfiler::VisitOMPThreadsClause(const OMPThreadsClause *) {}
void OMPClauseProfiler::VisitOMPSIMDClause(const OMPSIMDClause *) {}
void OMPClauseProfiler::VisitOMPNogroupClause(const OMPNogroupClause *) {}
+void OMPClauseProfiler::VisitOMPDestroyClause(const OMPDestroyClause *) {}
+
template<typename T>
void OMPClauseProfiler::VisitOMPClauseList(T *Node) {
for (auto *E : Node->varlists()) {
@@ -594,6 +609,20 @@ void OMPClauseProfiler::VisitOMPReductionClause(
if (E)
Profiler->VisitStmt(E);
}
+ if (C->getModifier() == clang::OMPC_REDUCTION_inscan) {
+ for (auto *E : C->copy_ops()) {
+ if (E)
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->copy_array_temps()) {
+ if (E)
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->copy_array_elems()) {
+ if (E)
+ Profiler->VisitStmt(E);
+ }
+ }
}
void OMPClauseProfiler::VisitOMPTaskReductionClause(
const OMPTaskReductionClause *C) {
@@ -710,6 +739,10 @@ OMPClauseProfiler::VisitOMPCopyprivateClause(const OMPCopyprivateClause *C) {
void OMPClauseProfiler::VisitOMPFlushClause(const OMPFlushClause *C) {
VisitOMPClauseList(C);
}
+void OMPClauseProfiler::VisitOMPDepobjClause(const OMPDepobjClause *C) {
+ if (const Expr *Depobj = C->getDepobj())
+ Profiler->VisitStmt(Depobj);
+}
void OMPClauseProfiler::VisitOMPDependClause(const OMPDependClause *C) {
VisitOMPClauseList(C);
}
@@ -765,6 +798,10 @@ void OMPClauseProfiler::VisitOMPUseDevicePtrClause(
const OMPUseDevicePtrClause *C) {
VisitOMPClauseList(C);
}
+void OMPClauseProfiler::VisitOMPUseDeviceAddrClause(
+ const OMPUseDeviceAddrClause *C) {
+ VisitOMPClauseList(C);
+}
void OMPClauseProfiler::VisitOMPIsDevicePtrClause(
const OMPIsDevicePtrClause *C) {
VisitOMPClauseList(C);
@@ -775,6 +812,28 @@ void OMPClauseProfiler::VisitOMPNontemporalClause(
for (auto *E : C->private_refs())
Profiler->VisitStmt(E);
}
+void OMPClauseProfiler::VisitOMPInclusiveClause(const OMPInclusiveClause *C) {
+ VisitOMPClauseList(C);
+}
+void OMPClauseProfiler::VisitOMPExclusiveClause(const OMPExclusiveClause *C) {
+ VisitOMPClauseList(C);
+}
+void OMPClauseProfiler::VisitOMPUsesAllocatorsClause(
+ const OMPUsesAllocatorsClause *C) {
+ for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
+ OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
+ Profiler->VisitStmt(D.Allocator);
+ if (D.AllocatorTraits)
+ Profiler->VisitStmt(D.AllocatorTraits);
+ }
+}
+void OMPClauseProfiler::VisitOMPAffinityClause(const OMPAffinityClause *C) {
+ if (const Expr *Modifier = C->getModifier())
+ Profiler->VisitStmt(Modifier);
+ for (const Expr *E : C->varlists())
+ Profiler->VisitStmt(E);
+}
+void OMPClauseProfiler::VisitOMPOrderClause(const OMPOrderClause *C) {}
} // namespace
void
@@ -875,6 +934,14 @@ void StmtProfiler::VisitOMPFlushDirective(const OMPFlushDirective *S) {
VisitOMPExecutableDirective(S);
}
+void StmtProfiler::VisitOMPDepobjDirective(const OMPDepobjDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
+void StmtProfiler::VisitOMPScanDirective(const OMPScanDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
void StmtProfiler::VisitOMPOrderedDirective(const OMPOrderedDirective *S) {
VisitOMPExecutableDirective(S);
}
@@ -1155,10 +1222,24 @@ void StmtProfiler::VisitArraySubscriptExpr(const ArraySubscriptExpr *S) {
VisitExpr(S);
}
+void StmtProfiler::VisitMatrixSubscriptExpr(const MatrixSubscriptExpr *S) {
+ VisitExpr(S);
+}
+
void StmtProfiler::VisitOMPArraySectionExpr(const OMPArraySectionExpr *S) {
VisitExpr(S);
}
+void StmtProfiler::VisitOMPArrayShapingExpr(const OMPArrayShapingExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitOMPIteratorExpr(const OMPIteratorExpr *S) {
+ VisitExpr(S);
+ for (unsigned I = 0, E = S->numOfIterators(); I < E; ++I)
+ VisitDecl(S->getIteratorDecl(I));
+}
+
void StmtProfiler::VisitCallExpr(const CallExpr *S) {
VisitExpr(S);
}
@@ -1335,9 +1416,52 @@ void StmtProfiler::VisitAtomicExpr(const AtomicExpr *S) {
void StmtProfiler::VisitConceptSpecializationExpr(
const ConceptSpecializationExpr *S) {
VisitExpr(S);
- VisitDecl(S->getFoundDecl());
- VisitTemplateArguments(S->getTemplateArgsAsWritten()->getTemplateArgs(),
- S->getTemplateArgsAsWritten()->NumTemplateArgs);
+ VisitDecl(S->getNamedConcept());
+ for (const TemplateArgument &Arg : S->getTemplateArguments())
+ VisitTemplateArgument(Arg);
+}
+
+void StmtProfiler::VisitRequiresExpr(const RequiresExpr *S) {
+ VisitExpr(S);
+ ID.AddInteger(S->getLocalParameters().size());
+ for (ParmVarDecl *LocalParam : S->getLocalParameters())
+ VisitDecl(LocalParam);
+ ID.AddInteger(S->getRequirements().size());
+ for (concepts::Requirement *Req : S->getRequirements()) {
+ if (auto *TypeReq = dyn_cast<concepts::TypeRequirement>(Req)) {
+ ID.AddInteger(concepts::Requirement::RK_Type);
+ ID.AddBoolean(TypeReq->isSubstitutionFailure());
+ if (!TypeReq->isSubstitutionFailure())
+ VisitType(TypeReq->getType()->getType());
+ } else if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(Req)) {
+ ID.AddInteger(concepts::Requirement::RK_Compound);
+ ID.AddBoolean(ExprReq->isExprSubstitutionFailure());
+ if (!ExprReq->isExprSubstitutionFailure())
+ Visit(ExprReq->getExpr());
+ // C++2a [expr.prim.req.compound]p1 Example:
+ // [...] The compound-requirement in C1 requires that x++ is a valid
+ // expression. It is equivalent to the simple-requirement x++; [...]
+ // We therefore do not profile isSimple() here.
+ ID.AddBoolean(ExprReq->getNoexceptLoc().isValid());
+ const concepts::ExprRequirement::ReturnTypeRequirement &RetReq =
+ ExprReq->getReturnTypeRequirement();
+ if (RetReq.isEmpty()) {
+ ID.AddInteger(0);
+ } else if (RetReq.isTypeConstraint()) {
+ ID.AddInteger(1);
+ Visit(RetReq.getTypeConstraint()->getImmediatelyDeclaredConstraint());
+ } else {
+ assert(RetReq.isSubstitutionFailure());
+ ID.AddInteger(2);
+ }
+ } else {
+ ID.AddInteger(concepts::Requirement::RK_Nested);
+ auto *NestedReq = cast<concepts::NestedRequirement>(Req);
+ ID.AddBoolean(NestedReq->isSubstitutionFailure());
+ if (!NestedReq->isSubstitutionFailure())
+ Visit(NestedReq->getConstraintExpr());
+ }
+ }
}
static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
@@ -1350,7 +1474,6 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
case OO_Array_New:
case OO_Array_Delete:
case OO_Arrow:
- case OO_Call:
case OO_Conditional:
case NUM_OVERLOADED_OPERATORS:
llvm_unreachable("Invalid operator call kind");
@@ -1492,8 +1615,8 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
return Stmt::BinaryOperatorClass;
case OO_Spaceship:
- // FIXME: Update this once we support <=> expressions.
- llvm_unreachable("<=> expressions not supported yet");
+ BinaryOp = BO_Cmp;
+ return Stmt::BinaryOperatorClass;
case OO_AmpAmp:
BinaryOp = BO_LAnd;
@@ -1524,6 +1647,9 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
case OO_Subscript:
return Stmt::ArraySubscriptExprClass;
+ case OO_Call:
+ return Stmt::CallExprClass;
+
case OO_Coawait:
UnaryOp = UO_Coawait;
return Stmt::UnaryOperatorClass;
@@ -1564,7 +1690,7 @@ void StmtProfiler::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
SC == Stmt::CompoundAssignOperatorClass)
ID.AddInteger(BinaryOp);
else
- assert(SC == Stmt::ArraySubscriptExprClass);
+ assert(SC == Stmt::ArraySubscriptExprClass || SC == Stmt::CallExprClass);
return;
}
@@ -1627,6 +1753,10 @@ void StmtProfiler::VisitBuiltinBitCastExpr(const BuiltinBitCastExpr *S) {
VisitType(S->getTypeInfoAsWritten()->getType());
}
+void StmtProfiler::VisitCXXAddrspaceCastExpr(const CXXAddrspaceCastExpr *S) {
+ VisitCXXNamedCastExpr(S);
+}
+
void StmtProfiler::VisitUserDefinedLiteral(const UserDefinedLiteral *S) {
VisitCallExpr(S);
}
@@ -1947,6 +2077,8 @@ void StmtProfiler::VisitSourceLocExpr(const SourceLocExpr *E) {
VisitExpr(E);
}
+void StmtProfiler::VisitRecoveryExpr(const RecoveryExpr *E) { VisitExpr(E); }
+
void StmtProfiler::VisitObjCStringLiteral(const ObjCStringLiteral *S) {
VisitExpr(S);
}
diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp
index db16c2a06b64f..6a3d2b30e46ee 100644
--- a/clang/lib/AST/TemplateBase.cpp
+++ b/clang/lib/AST/TemplateBase.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DependenceFlags.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/PrettyPrinter.h"
@@ -111,84 +112,60 @@ TemplateArgument::CreatePackCopy(ASTContext &Context,
return TemplateArgument(Args.copy(Context));
}
-bool TemplateArgument::isDependent() const {
+TemplateArgumentDependence TemplateArgument::getDependence() const {
+ auto Deps = TemplateArgumentDependence::None;
switch (getKind()) {
case Null:
llvm_unreachable("Should not have a NULL template argument");
case Type:
- return getAsType()->isDependentType() ||
- isa<PackExpansionType>(getAsType());
+ Deps = toTemplateArgumentDependence(getAsType()->getDependence());
+ if (isa<PackExpansionType>(getAsType()))
+ Deps |= TemplateArgumentDependence::Dependent;
+ return Deps;
case Template:
- return getAsTemplate().isDependent();
+ return toTemplateArgumentDependence(getAsTemplate().getDependence());
case TemplateExpansion:
- return true;
+ return TemplateArgumentDependence::Dependent |
+ TemplateArgumentDependence::Instantiation;
- case Declaration:
- if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
- return DC->isDependentContext();
- return getAsDecl()->getDeclContext()->isDependentContext();
+ case Declaration: {
+ auto *DC = dyn_cast<DeclContext>(getAsDecl());
+ if (!DC)
+ DC = getAsDecl()->getDeclContext();
+ if (DC->isDependentContext())
+ Deps = TemplateArgumentDependence::Dependent |
+ TemplateArgumentDependence::Instantiation;
+ return Deps;
+ }
case NullPtr:
- return false;
-
case Integral:
- // Never dependent
- return false;
+ return TemplateArgumentDependence::None;
case Expression:
- return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent() ||
- isa<PackExpansionExpr>(getAsExpr()));
+ Deps = toTemplateArgumentDependence(getAsExpr()->getDependence());
+ if (isa<PackExpansionExpr>(getAsExpr()))
+ Deps |= TemplateArgumentDependence::Dependent |
+ TemplateArgumentDependence::Instantiation;
+ return Deps;
case Pack:
for (const auto &P : pack_elements())
- if (P.isDependent())
- return true;
- return false;
+ Deps |= P.getDependence();
+ return Deps;
}
+ llvm_unreachable("unhandled ArgKind");
+}
- llvm_unreachable("Invalid TemplateArgument Kind!");
+bool TemplateArgument::isDependent() const {
+ return getDependence() & TemplateArgumentDependence::Dependent;
}
bool TemplateArgument::isInstantiationDependent() const {
- switch (getKind()) {
- case Null:
- llvm_unreachable("Should not have a NULL template argument");
-
- case Type:
- return getAsType()->isInstantiationDependentType();
-
- case Template:
- return getAsTemplate().isInstantiationDependent();
-
- case TemplateExpansion:
- return true;
-
- case Declaration:
- if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
- return DC->isDependentContext();
- return getAsDecl()->getDeclContext()->isDependentContext();
-
- case NullPtr:
- return false;
-
- case Integral:
- // Never dependent
- return false;
-
- case Expression:
- return getAsExpr()->isInstantiationDependent();
-
- case Pack:
- for (const auto &P : pack_elements())
- if (P.isInstantiationDependent())
- return true;
- return false;
- }
-
- llvm_unreachable("Invalid TemplateArgument Kind!");
+ return getDependence() & TemplateArgumentDependence::Instantiation;
}
bool TemplateArgument::isPackExpansion() const {
@@ -215,38 +192,7 @@ bool TemplateArgument::isPackExpansion() const {
}
bool TemplateArgument::containsUnexpandedParameterPack() const {
- switch (getKind()) {
- case Null:
- case Declaration:
- case Integral:
- case TemplateExpansion:
- case NullPtr:
- break;
-
- case Type:
- if (getAsType()->containsUnexpandedParameterPack())
- return true;
- break;
-
- case Template:
- if (getAsTemplate().containsUnexpandedParameterPack())
- return true;
- break;
-
- case Expression:
- if (getAsExpr()->containsUnexpandedParameterPack())
- return true;
- break;
-
- case Pack:
- for (const auto &P : pack_elements())
- if (P.containsUnexpandedParameterPack())
- return true;
-
- break;
- }
-
- return false;
+ return getDependence() & TemplateArgumentDependence::UnexpandedPack;
}
Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
@@ -406,13 +352,9 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
case Declaration: {
NamedDecl *ND = getAsDecl();
- Out << '&';
- if (ND->getDeclName()) {
- // FIXME: distinguish between pointer and reference args?
- ND->printQualifiedName(Out);
- } else {
- Out << "(anonymous)";
- }
+ if (!getParamTypeForDecl()->isReferenceType())
+ Out << '&';
+ ND->printQualifiedName(Out);
break;
}
@@ -561,7 +503,7 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
}
const ASTTemplateArgumentListInfo *
-ASTTemplateArgumentListInfo::Create(ASTContext &C,
+ASTTemplateArgumentListInfo::Create(const ASTContext &C,
const TemplateArgumentListInfo &List) {
std::size_t size = totalSizeToAlloc<TemplateArgumentLoc>(List.size());
void *Mem = C.Allocate(size, alignof(ASTTemplateArgumentListInfo));
@@ -601,20 +543,14 @@ void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
void ASTTemplateKWAndArgsInfo::initializeFrom(
SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
- TemplateArgumentLoc *OutArgArray, bool &Dependent,
- bool &InstantiationDependent, bool &ContainsUnexpandedParameterPack) {
+ TemplateArgumentLoc *OutArgArray, TemplateArgumentDependence &Deps) {
this->TemplateKWLoc = TemplateKWLoc;
LAngleLoc = Info.getLAngleLoc();
RAngleLoc = Info.getRAngleLoc();
NumTemplateArgs = Info.size();
for (unsigned i = 0; i != NumTemplateArgs; ++i) {
- Dependent = Dependent || Info[i].getArgument().isDependent();
- InstantiationDependent = InstantiationDependent ||
- Info[i].getArgument().isInstantiationDependent();
- ContainsUnexpandedParameterPack =
- ContainsUnexpandedParameterPack ||
- Info[i].getArgument().containsUnexpandedParameterPack();
+ Deps |= Info[i].getArgument().getDependence();
new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
}
diff --git a/clang/lib/AST/TemplateName.cpp b/clang/lib/AST/TemplateName.cpp
index 06e1dcec74492..40a8736ae1afd 100644
--- a/clang/lib/AST/TemplateName.cpp
+++ b/clang/lib/AST/TemplateName.cpp
@@ -11,8 +11,10 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/TemplateName.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DependenceFlags.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/TemplateBase.h"
@@ -168,52 +170,54 @@ TemplateName TemplateName::getNameToSubstitute() const {
return TemplateName(Decl);
}
-bool TemplateName::isDependent() const {
+TemplateNameDependence TemplateName::getDependence() const {
+ auto D = TemplateNameDependence::None;
+ switch (getKind()) {
+ case TemplateName::NameKind::QualifiedTemplate:
+ D |= toTemplateNameDependence(
+ getAsQualifiedTemplateName()->getQualifier()->getDependence());
+ break;
+ case TemplateName::NameKind::DependentTemplate:
+ D |= toTemplateNameDependence(
+ getAsDependentTemplateName()->getQualifier()->getDependence());
+ break;
+ case TemplateName::NameKind::SubstTemplateTemplateParmPack:
+ D |= TemplateNameDependence::UnexpandedPack;
+ break;
+ case TemplateName::NameKind::OverloadedTemplate:
+ llvm_unreachable("overloaded templates shouldn't survive to here.");
+ default:
+ break;
+ }
if (TemplateDecl *Template = getAsTemplateDecl()) {
- if (isa<TemplateTemplateParmDecl>(Template))
- return true;
+ if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) {
+ D |= TemplateNameDependence::DependentInstantiation;
+ if (TTP->isParameterPack())
+ D |= TemplateNameDependence::UnexpandedPack;
+ }
// FIXME: Hack, getDeclContext() can be null if Template is still
// initializing due to PCH reading, so we check it before using it.
// Should probably modify TemplateSpecializationType to allow constructing
// it without the isDependent() checking.
- return Template->getDeclContext() &&
- Template->getDeclContext()->isDependentContext();
+ if (Template->getDeclContext() &&
+ Template->getDeclContext()->isDependentContext())
+ D |= TemplateNameDependence::DependentInstantiation;
+ } else {
+ D |= TemplateNameDependence::DependentInstantiation;
}
+ return D;
+}
- assert(!getAsOverloadedTemplate() &&
- "overloaded templates shouldn't survive to here");
-
- return true;
+bool TemplateName::isDependent() const {
+ return getDependence() & TemplateNameDependence::Dependent;
}
bool TemplateName::isInstantiationDependent() const {
- if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
- if (QTN->getQualifier()->isInstantiationDependent())
- return true;
- }
-
- return isDependent();
+ return getDependence() & TemplateNameDependence::Instantiation;
}
bool TemplateName::containsUnexpandedParameterPack() const {
- if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
- if (QTN->getQualifier()->containsUnexpandedParameterPack())
- return true;
- }
-
- if (TemplateDecl *Template = getAsTemplateDecl()) {
- if (TemplateTemplateParmDecl *TTP
- = dyn_cast<TemplateTemplateParmDecl>(Template))
- return TTP->isParameterPack();
-
- return false;
- }
-
- if (DependentTemplateName *DTN = getAsDependentTemplateName())
- return DTN->getQualifier() &&
- DTN->getQualifier()->containsUnexpandedParameterPack();
-
- return getAsSubstTemplateTemplateParmPack() != nullptr;
+ return getDependence() & TemplateNameDependence::UnexpandedPack;
}
void
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index 965ad17fcfa5b..5b0a0ac392c00 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -11,10 +11,19 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/TextNodeDumper.h"
+#include "clang/AST/APValue.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/LocInfoType.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/TypeTraits.h"
+
+#include <algorithm>
+#include <utility>
using namespace clang;
@@ -47,12 +56,15 @@ static void dumpPreviousDecl(raw_ostream &OS, const Decl *D) {
llvm_unreachable("Decl that isn't part of DeclNodes.inc!");
}
-TextNodeDumper::TextNodeDumper(raw_ostream &OS, bool ShowColors,
- const SourceManager *SM,
- const PrintingPolicy &PrintPolicy,
- const comments::CommandTraits *Traits)
- : TextTreeStructure(OS, ShowColors), OS(OS), ShowColors(ShowColors), SM(SM),
- PrintPolicy(PrintPolicy), Traits(Traits) {}
+TextNodeDumper::TextNodeDumper(raw_ostream &OS, const ASTContext &Context,
+ bool ShowColors)
+ : TextTreeStructure(OS, ShowColors), OS(OS), ShowColors(ShowColors),
+ Context(&Context), SM(&Context.getSourceManager()),
+ PrintPolicy(Context.getPrintingPolicy()),
+ Traits(&Context.getCommentCommandTraits()) {}
+
+TextNodeDumper::TextNodeDumper(raw_ostream &OS, bool ShowColors)
+ : TextTreeStructure(OS, ShowColors), OS(OS), ShowColors(ShowColors) {}
void TextNodeDumper::Visit(const comments::Comment *C,
const comments::FullComment *FC) {
@@ -121,12 +133,14 @@ void TextNodeDumper::Visit(const Stmt *Node) {
dumpPointer(Node);
dumpSourceRange(Node->getSourceRange());
- if (Node->isOMPStructuredBlock())
- OS << " openmp_structured_block";
-
if (const auto *E = dyn_cast<Expr>(Node)) {
dumpType(E->getType());
+ if (E->containsErrors()) {
+ ColorScope Color(OS, ShowColors, ErrorsColor);
+ OS << " contains-errors";
+ }
+
{
ColorScope Color(OS, ShowColors, ValueKindColor);
switch (E->getValueKind()) {
@@ -158,6 +172,9 @@ void TextNodeDumper::Visit(const Stmt *Node) {
case OK_VectorComponent:
OS << " vectorcomponent";
break;
+ case OK_MatrixComponent:
+ OS << " matrixcomponent";
+ break;
}
}
}
@@ -193,6 +210,11 @@ void TextNodeDumper::Visit(const Type *T) {
if (SingleStepDesugar != QualType(T, 0))
OS << " sugar";
+ if (T->containsErrors()) {
+ ColorScope Color(OS, ShowColors, ErrorsColor);
+ OS << " contains-errors";
+ }
+
if (T->isDependentType())
OS << " dependent";
else if (T->isInstantiationDependentType())
@@ -243,7 +265,7 @@ void TextNodeDumper::Visit(const Decl *D) {
const_cast<NamedDecl *>(ND)))
AddChild([=] { OS << "also in " << M->getFullModuleName(); });
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
- if (ND->isHidden())
+ if (!ND->isUnconditionallyVisible())
OS << " hidden";
if (D->isImplicit())
OS << " implicit";
@@ -310,7 +332,7 @@ void TextNodeDumper::Visit(const OMPClause *C) {
}
{
ColorScope Color(OS, ShowColors, AttrColor);
- StringRef ClauseName(getOpenMPClauseName(C->getClauseKind()));
+ StringRef ClauseName(llvm::omp::getOpenMPClauseName(C->getClauseKind()));
OS << "OMP" << ClauseName.substr(/*Start=*/0, /*N=*/1).upper()
<< ClauseName.drop_front() << "Clause";
}
@@ -333,6 +355,218 @@ void TextNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) {
OS << " selected";
}
+static double GetApproxValue(const llvm::APFloat &F) {
+ llvm::APFloat V = F;
+ bool ignored;
+ V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven,
+ &ignored);
+ return V.convertToDouble();
+}
+
+/// True if the \p APValue \p Value can be folded onto the current line.
+static bool isSimpleAPValue(const APValue &Value) {
+ switch (Value.getKind()) {
+ case APValue::None:
+ case APValue::Indeterminate:
+ case APValue::Int:
+ case APValue::Float:
+ case APValue::FixedPoint:
+ case APValue::ComplexInt:
+ case APValue::ComplexFloat:
+ case APValue::LValue:
+ case APValue::MemberPointer:
+ case APValue::AddrLabelDiff:
+ return true;
+ case APValue::Vector:
+ case APValue::Array:
+ case APValue::Struct:
+ return false;
+ case APValue::Union:
+ return isSimpleAPValue(Value.getUnionValue());
+ }
+ llvm_unreachable("unexpected APValue kind!");
+}
+
+/// Dump the children of the \p APValue \p Value.
+///
+/// \param[in] Value The \p APValue to visit
+/// \param[in] Ty The \p QualType passed to \p Visit
+///
+/// \param[in] IdxToChildFun A function mapping an \p APValue and an index
+/// to one of the child of the \p APValue
+///
+/// \param[in] NumChildren \p IdxToChildFun will be called on \p Value with
+/// the indices in the range \p [0,NumChildren(
+///
+/// \param[in] LabelSingular The label to use on a line with a single child
+/// \param[in] LabelPlurial The label to use on a line with multiple children
+void TextNodeDumper::dumpAPValueChildren(
+ const APValue &Value, QualType Ty,
+ const APValue &(*IdxToChildFun)(const APValue &, unsigned),
+ unsigned NumChildren, StringRef LabelSingular, StringRef LabelPlurial) {
+ // To save some vertical space we print up to MaxChildrenPerLine APValues
+ // considered to be simple (by isSimpleAPValue) on a single line.
+ constexpr unsigned MaxChildrenPerLine = 4;
+ unsigned I = 0;
+ while (I < NumChildren) {
+ unsigned J = I;
+ while (J < NumChildren) {
+ if (isSimpleAPValue(IdxToChildFun(Value, J)) &&
+ (J - I < MaxChildrenPerLine)) {
+ ++J;
+ continue;
+ }
+ break;
+ }
+
+ J = std::max(I + 1, J);
+
+ // Print [I,J) on a single line.
+ AddChild(J - I > 1 ? LabelPlurial : LabelSingular, [=]() {
+ for (unsigned X = I; X < J; ++X) {
+ Visit(IdxToChildFun(Value, X), Ty);
+ if (X + 1 != J)
+ OS << ", ";
+ }
+ });
+ I = J;
+ }
+}
+
+void TextNodeDumper::Visit(const APValue &Value, QualType Ty) {
+ ColorScope Color(OS, ShowColors, ValueKindColor);
+ switch (Value.getKind()) {
+ case APValue::None:
+ OS << "None";
+ return;
+ case APValue::Indeterminate:
+ OS << "Indeterminate";
+ return;
+ case APValue::Int:
+ OS << "Int ";
+ {
+ ColorScope Color(OS, ShowColors, ValueColor);
+ OS << Value.getInt();
+ }
+ return;
+ case APValue::Float:
+ OS << "Float ";
+ {
+ ColorScope Color(OS, ShowColors, ValueColor);
+ OS << GetApproxValue(Value.getFloat());
+ }
+ return;
+ case APValue::FixedPoint:
+ OS << "FixedPoint ";
+ {
+ ColorScope Color(OS, ShowColors, ValueColor);
+ OS << Value.getFixedPoint();
+ }
+ return;
+ case APValue::Vector: {
+ unsigned VectorLength = Value.getVectorLength();
+ OS << "Vector length=" << VectorLength;
+
+ dumpAPValueChildren(
+ Value, Ty,
+ [](const APValue &Value, unsigned Index) -> const APValue & {
+ return Value.getVectorElt(Index);
+ },
+ VectorLength, "element", "elements");
+ return;
+ }
+ case APValue::ComplexInt:
+ OS << "ComplexInt ";
+ {
+ ColorScope Color(OS, ShowColors, ValueColor);
+ OS << Value.getComplexIntReal() << " + " << Value.getComplexIntImag()
+ << 'i';
+ }
+ return;
+ case APValue::ComplexFloat:
+ OS << "ComplexFloat ";
+ {
+ ColorScope Color(OS, ShowColors, ValueColor);
+ OS << GetApproxValue(Value.getComplexFloatReal()) << " + "
+ << GetApproxValue(Value.getComplexFloatImag()) << 'i';
+ }
+ return;
+ case APValue::LValue:
+ (void)Context;
+ OS << "LValue <todo>";
+ return;
+ case APValue::Array: {
+ unsigned ArraySize = Value.getArraySize();
+ unsigned NumInitializedElements = Value.getArrayInitializedElts();
+ OS << "Array size=" << ArraySize;
+
+ dumpAPValueChildren(
+ Value, Ty,
+ [](const APValue &Value, unsigned Index) -> const APValue & {
+ return Value.getArrayInitializedElt(Index);
+ },
+ NumInitializedElements, "element", "elements");
+
+ if (Value.hasArrayFiller()) {
+ AddChild("filler", [=] {
+ {
+ ColorScope Color(OS, ShowColors, ValueColor);
+ OS << ArraySize - NumInitializedElements << " x ";
+ }
+ Visit(Value.getArrayFiller(), Ty);
+ });
+ }
+
+ return;
+ }
+ case APValue::Struct: {
+ OS << "Struct";
+
+ dumpAPValueChildren(
+ Value, Ty,
+ [](const APValue &Value, unsigned Index) -> const APValue & {
+ return Value.getStructBase(Index);
+ },
+ Value.getStructNumBases(), "base", "bases");
+
+ dumpAPValueChildren(
+ Value, Ty,
+ [](const APValue &Value, unsigned Index) -> const APValue & {
+ return Value.getStructField(Index);
+ },
+ Value.getStructNumFields(), "field", "fields");
+
+ return;
+ }
+ case APValue::Union: {
+ OS << "Union";
+ {
+ ColorScope Color(OS, ShowColors, ValueColor);
+ if (const FieldDecl *FD = Value.getUnionField())
+ OS << " ." << *cast<NamedDecl>(FD);
+ }
+ // If the union value is considered to be simple, fold it into the
+ // current line to save some vertical space.
+ const APValue &UnionValue = Value.getUnionValue();
+ if (isSimpleAPValue(UnionValue)) {
+ OS << ' ';
+ Visit(UnionValue, Ty);
+ } else {
+ AddChild([=] { Visit(UnionValue, Ty); });
+ }
+
+ return;
+ }
+ case APValue::MemberPointer:
+ OS << "MemberPointer <todo>";
+ return;
+ case APValue::AddrLabelDiff:
+ OS << "AddrLabelDiff <todo>";
+ return;
+ }
+ llvm_unreachable("Unknown APValue kind!");
+}
+
void TextNodeDumper::dumpPointer(const void *Ptr) {
ColorScope Color(OS, ShowColors, AddressColor);
OS << ' ' << Ptr;
@@ -432,19 +666,27 @@ void TextNodeDumper::dumpName(const NamedDecl *ND) {
}
void TextNodeDumper::dumpAccessSpecifier(AccessSpecifier AS) {
- switch (AS) {
- case AS_none:
- break;
- case AS_public:
- OS << "public";
- break;
- case AS_protected:
- OS << "protected";
- break;
- case AS_private:
- OS << "private";
- break;
- }
+ const auto AccessSpelling = getAccessSpelling(AS);
+ if (AccessSpelling.empty())
+ return;
+ OS << AccessSpelling;
+}
+
+void TextNodeDumper::dumpCleanupObject(
+ const ExprWithCleanups::CleanupObject &C) {
+ if (auto *BD = C.dyn_cast<BlockDecl *>())
+ dumpDeclRef(BD, "cleanup");
+ else if (auto *CLE = C.dyn_cast<CompoundLiteralExpr *>())
+ AddChild([=] {
+ OS << "cleanup ";
+ {
+ ColorScope Color(OS, ShowColors, StmtColor);
+ OS << CLE->getStmtClassName();
+ }
+ dumpPointer(CLE);
+ });
+ else
+ llvm_unreachable("unexpected cleanup type");
}
void TextNodeDumper::dumpDeclRef(const Decl *D, StringRef Label) {
@@ -687,11 +929,9 @@ void TextNodeDumper::VisitCaseStmt(const CaseStmt *Node) {
}
void TextNodeDumper::VisitConstantExpr(const ConstantExpr *Node) {
- if (Node->getResultAPValueKind() != APValue::None) {
- ColorScope Color(OS, ShowColors, ValueColor);
- OS << " ";
- Node->getAPValueResult().dump(OS);
- }
+ if (Node->hasAPValueResult())
+ AddChild("value",
+ [=] { Visit(Node->getAPValueResult(), Node->getType()); });
}
void TextNodeDumper::VisitCallExpr(const CallExpr *Node) {
@@ -699,6 +939,14 @@ void TextNodeDumper::VisitCallExpr(const CallExpr *Node) {
OS << " adl";
}
+void TextNodeDumper::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Node) {
+ const char *OperatorSpelling = clang::getOperatorSpelling(Node->getOperator());
+ if (OperatorSpelling)
+ OS << " '" << OperatorSpelling << "'";
+
+ VisitCallExpr(Node);
+}
+
void TextNodeDumper::VisitCastExpr(const CastExpr *Node) {
OS << " <";
{
@@ -809,23 +1057,8 @@ void TextNodeDumper::VisitUnaryOperator(const UnaryOperator *Node) {
void TextNodeDumper::VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *Node) {
- switch (Node->getKind()) {
- case UETT_SizeOf:
- OS << " sizeof";
- break;
- case UETT_AlignOf:
- OS << " alignof";
- break;
- case UETT_VecStep:
- OS << " vec_step";
- break;
- case UETT_OpenMPRequiredSimdAlign:
- OS << " __builtin_omp_required_simd_align";
- break;
- case UETT_PreferredAlignOf:
- OS << " __alignof";
- break;
- }
+ OS << " " << getTraitSpelling(Node->getKind());
+
if (Node->isArgumentType())
dumpType(Node->getArgumentType());
}
@@ -939,6 +1172,18 @@ void TextNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *Node) {
}
}
+void TextNodeDumper::VisitTypeTraitExpr(const TypeTraitExpr *Node) {
+ OS << " " << getTraitSpelling(Node->getTrait());
+}
+
+void TextNodeDumper::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *Node) {
+ OS << " " << getTraitSpelling(Node->getTrait());
+}
+
+void TextNodeDumper::VisitExpressionTraitExpr(const ExpressionTraitExpr *Node) {
+ OS << " " << getTraitSpelling(Node->getTrait());
+}
+
void TextNodeDumper::VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *Node) {
if (const ValueDecl *VD = Node->getExtendingDecl()) {
@@ -949,7 +1194,7 @@ void TextNodeDumper::VisitMaterializeTemporaryExpr(
void TextNodeDumper::VisitExprWithCleanups(const ExprWithCleanups *Node) {
for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i)
- dumpDeclRef(Node->getObject(i), "cleanup");
+ dumpCleanupObject(Node->getObject(i));
}
void TextNodeDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) {
@@ -1065,6 +1310,23 @@ void TextNodeDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node) {
OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no");
}
+void TextNodeDumper::VisitOMPIteratorExpr(const OMPIteratorExpr *Node) {
+ OS << " ";
+ for (unsigned I = 0, E = Node->numOfIterators(); I < E; ++I) {
+ Visit(Node->getIteratorDecl(I));
+ OS << " = ";
+ const OMPIteratorExpr::IteratorRange Range = Node->getIteratorRange(I);
+ OS << " begin ";
+ Visit(Range.Begin);
+ OS << " end ";
+ Visit(Range.End);
+ if (Range.Step) {
+ OS << " step ";
+ Visit(Range.Step);
+ }
+ }
+}
+
void TextNodeDumper::VisitRValueReferenceType(const ReferenceType *T) {
if (T->isSpelledAsLValue())
OS << " written as lvalue reference";
@@ -1201,6 +1463,11 @@ void TextNodeDumper::VisitAutoType(const AutoType *T) {
OS << " decltype(auto)";
if (!T->isDeduced())
OS << " undeduced";
+ if (T->isConstrained()) {
+ dumpDeclRef(T->getTypeConstraintConcept());
+ for (const auto &Arg : T->getTypeConstraintArguments())
+ VisitTemplateArgument(Arg);
+ }
}
void TextNodeDumper::VisitTemplateSpecializationType(
@@ -1402,6 +1669,16 @@ void TextNodeDumper::VisitVarDecl(const VarDecl *D) {
OS << " destroyed";
if (D->isParameterPack())
OS << " pack";
+
+ if (D->hasInit()) {
+ const Expr *E = D->getInit();
+ // Only dump the value of constexpr VarDecls for now.
+ if (E && !E->isValueDependent() && D->isConstexpr()) {
+ const APValue *Value = D->evaluateValue();
+ if (Value)
+ AddChild("value", [=] { Visit(*Value, E->getType()); });
+ }
+ }
}
void TextNodeDumper::VisitBindingDecl(const BindingDecl *D) {
@@ -1491,7 +1768,8 @@ void TextNodeDumper::VisitOMPRequiresDecl(const OMPRequiresDecl *D) {
}
{
ColorScope Color(OS, ShowColors, AttrColor);
- StringRef ClauseName(getOpenMPClauseName(C->getClauseKind()));
+ StringRef ClauseName(
+ llvm::omp::getOpenMPClauseName(C->getClauseKind()));
OS << "OMP" << ClauseName.substr(/*Start=*/0, /*N=*/1).upper()
<< ClauseName.drop_front() << "Clause";
}
@@ -1624,6 +1902,7 @@ void TextNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
ColorScope Color(OS, ShowColors, DeclKindNameColor);
OS << "CopyAssignment";
}
+ FLAG(hasSimpleCopyAssignment, simple);
FLAG(hasTrivialCopyAssignment, trivial);
FLAG(hasNonTrivialCopyAssignment, non_trivial);
FLAG(hasCopyAssignmentWithConstParam, has_const_param);
@@ -1914,35 +2193,35 @@ void TextNodeDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
else if (D->getPropertyImplementation() == ObjCPropertyDecl::Optional)
OS << " optional";
- ObjCPropertyDecl::PropertyAttributeKind Attrs = D->getPropertyAttributes();
- if (Attrs != ObjCPropertyDecl::OBJC_PR_noattr) {
- if (Attrs & ObjCPropertyDecl::OBJC_PR_readonly)
+ ObjCPropertyAttribute::Kind Attrs = D->getPropertyAttributes();
+ if (Attrs != ObjCPropertyAttribute::kind_noattr) {
+ if (Attrs & ObjCPropertyAttribute::kind_readonly)
OS << " readonly";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_assign)
+ if (Attrs & ObjCPropertyAttribute::kind_assign)
OS << " assign";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_readwrite)
+ if (Attrs & ObjCPropertyAttribute::kind_readwrite)
OS << " readwrite";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_retain)
+ if (Attrs & ObjCPropertyAttribute::kind_retain)
OS << " retain";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_copy)
+ if (Attrs & ObjCPropertyAttribute::kind_copy)
OS << " copy";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_nonatomic)
+ if (Attrs & ObjCPropertyAttribute::kind_nonatomic)
OS << " nonatomic";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_atomic)
+ if (Attrs & ObjCPropertyAttribute::kind_atomic)
OS << " atomic";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_weak)
+ if (Attrs & ObjCPropertyAttribute::kind_weak)
OS << " weak";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_strong)
+ if (Attrs & ObjCPropertyAttribute::kind_strong)
OS << " strong";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained)
+ if (Attrs & ObjCPropertyAttribute::kind_unsafe_unretained)
OS << " unsafe_unretained";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_class)
+ if (Attrs & ObjCPropertyAttribute::kind_class)
OS << " class";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_direct)
+ if (Attrs & ObjCPropertyAttribute::kind_direct)
OS << " direct";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_getter)
+ if (Attrs & ObjCPropertyAttribute::kind_getter)
dumpDeclRef(D->getGetterMethodDecl(), "getter");
- if (Attrs & ObjCPropertyDecl::OBJC_PR_setter)
+ if (Attrs & ObjCPropertyAttribute::kind_setter)
dumpDeclRef(D->getSetterMethodDecl(), "setter");
}
}
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index c5ad711d872e0..10a6a26101302 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -20,6 +20,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DependenceFlags.h"
#include "clang/AST/Expr.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/NonTrivialTypeVisitor.h"
@@ -123,14 +124,15 @@ ArrayType::ArrayType(TypeClass tc, QualType et, QualType can,
//
// template<int ...N> int arr[] = {N...};
: Type(tc, can,
- et->isDependentType() || (sz && sz->isValueDependent()) ||
- tc == DependentSizedArray,
- et->isInstantiationDependentType() ||
- (sz && sz->isInstantiationDependent()) ||
- tc == DependentSizedArray,
- (tc == VariableArray || et->isVariablyModifiedType()),
- et->containsUnexpandedParameterPack() ||
- (sz && sz->containsUnexpandedParameterPack())),
+ et->getDependence() |
+ (sz ? toTypeDependence(
+ turnValueToTypeDependence(sz->getDependence()))
+ : TypeDependence::None) |
+ (tc == VariableArray ? TypeDependence::VariablyModified
+ : TypeDependence::None) |
+ (tc == DependentSizedArray
+ ? TypeDependence::DependentInstantiation
+ : TypeDependence::None)),
ElementType(et) {
ArrayTypeBits.IndexTypeQuals = tq;
ArrayTypeBits.SizeModifier = sm;
@@ -217,14 +219,16 @@ void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID,
E->Profile(ID, Context, true);
}
-DependentVectorType::DependentVectorType(
- const ASTContext &Context, QualType ElementType, QualType CanonType,
- Expr *SizeExpr, SourceLocation Loc, VectorType::VectorKind VecKind)
- : Type(DependentVector, CanonType, /*Dependent=*/true,
- /*InstantiationDependent=*/true,
- ElementType->isVariablyModifiedType(),
- ElementType->containsUnexpandedParameterPack() ||
- (SizeExpr && SizeExpr->containsUnexpandedParameterPack())),
+DependentVectorType::DependentVectorType(const ASTContext &Context,
+ QualType ElementType,
+ QualType CanonType, Expr *SizeExpr,
+ SourceLocation Loc,
+ VectorType::VectorKind VecKind)
+ : Type(DependentVector, CanonType,
+ TypeDependence::DependentInstantiation |
+ ElementType->getDependence() |
+ (SizeExpr ? toTypeDependence(SizeExpr->getDependence())
+ : TypeDependence::None)),
Context(Context), ElementType(ElementType), SizeExpr(SizeExpr), Loc(Loc) {
VectorTypeBits.VecKind = VecKind;
}
@@ -238,19 +242,16 @@ void DependentVectorType::Profile(llvm::FoldingSetNodeID &ID,
SizeExpr->Profile(ID, Context, true);
}
-DependentSizedExtVectorType::DependentSizedExtVectorType(const
- ASTContext &Context,
- QualType ElementType,
- QualType can,
- Expr *SizeExpr,
- SourceLocation loc)
- : Type(DependentSizedExtVector, can, /*Dependent=*/true,
- /*InstantiationDependent=*/true,
- ElementType->isVariablyModifiedType(),
- (ElementType->containsUnexpandedParameterPack() ||
- (SizeExpr && SizeExpr->containsUnexpandedParameterPack()))),
- Context(Context), SizeExpr(SizeExpr), ElementType(ElementType),
- loc(loc) {}
+DependentSizedExtVectorType::DependentSizedExtVectorType(
+ const ASTContext &Context, QualType ElementType, QualType can,
+ Expr *SizeExpr, SourceLocation loc)
+ : Type(DependentSizedExtVector, can,
+ TypeDependence::DependentInstantiation |
+ ElementType->getDependence() |
+ (SizeExpr ? toTypeDependence(SizeExpr->getDependence())
+ : TypeDependence::None)),
+ Context(Context), SizeExpr(SizeExpr), ElementType(ElementType), loc(loc) {
+}
void
DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID,
@@ -260,15 +261,16 @@ DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID,
SizeExpr->Profile(ID, Context, true);
}
-DependentAddressSpaceType::DependentAddressSpaceType(
- const ASTContext &Context, QualType PointeeType, QualType can,
- Expr *AddrSpaceExpr, SourceLocation loc)
- : Type(DependentAddressSpace, can, /*Dependent=*/true,
- /*InstantiationDependent=*/true,
- PointeeType->isVariablyModifiedType(),
- (PointeeType->containsUnexpandedParameterPack() ||
- (AddrSpaceExpr &&
- AddrSpaceExpr->containsUnexpandedParameterPack()))),
+DependentAddressSpaceType::DependentAddressSpaceType(const ASTContext &Context,
+ QualType PointeeType,
+ QualType can,
+ Expr *AddrSpaceExpr,
+ SourceLocation loc)
+ : Type(DependentAddressSpace, can,
+ TypeDependence::DependentInstantiation |
+ PointeeType->getDependence() |
+ (AddrSpaceExpr ? toTypeDependence(AddrSpaceExpr->getDependence())
+ : TypeDependence::None)),
Context(Context), AddrSpaceExpr(AddrSpaceExpr), PointeeType(PointeeType),
loc(loc) {}
@@ -280,21 +282,89 @@ void DependentAddressSpaceType::Profile(llvm::FoldingSetNodeID &ID,
AddrSpaceExpr->Profile(ID, Context, true);
}
+MatrixType::MatrixType(TypeClass tc, QualType matrixType, QualType canonType,
+ const Expr *RowExpr, const Expr *ColumnExpr)
+ : Type(tc, canonType,
+ (RowExpr ? (matrixType->getDependence() | TypeDependence::Dependent |
+ TypeDependence::Instantiation |
+ (matrixType->isVariablyModifiedType()
+ ? TypeDependence::VariablyModified
+ : TypeDependence::None) |
+ (matrixType->containsUnexpandedParameterPack() ||
+ (RowExpr &&
+ RowExpr->containsUnexpandedParameterPack()) ||
+ (ColumnExpr &&
+ ColumnExpr->containsUnexpandedParameterPack())
+ ? TypeDependence::UnexpandedPack
+ : TypeDependence::None))
+ : matrixType->getDependence())),
+ ElementType(matrixType) {}
+
+ConstantMatrixType::ConstantMatrixType(QualType matrixType, unsigned nRows,
+ unsigned nColumns, QualType canonType)
+ : ConstantMatrixType(ConstantMatrix, matrixType, nRows, nColumns,
+ canonType) {}
+
+ConstantMatrixType::ConstantMatrixType(TypeClass tc, QualType matrixType,
+ unsigned nRows, unsigned nColumns,
+ QualType canonType)
+ : MatrixType(tc, matrixType, canonType) {
+ ConstantMatrixTypeBits.NumRows = nRows;
+ ConstantMatrixTypeBits.NumColumns = nColumns;
+}
+
+DependentSizedMatrixType::DependentSizedMatrixType(
+ const ASTContext &CTX, QualType ElementType, QualType CanonicalType,
+ Expr *RowExpr, Expr *ColumnExpr, SourceLocation loc)
+ : MatrixType(DependentSizedMatrix, ElementType, CanonicalType, RowExpr,
+ ColumnExpr),
+ Context(CTX), RowExpr(RowExpr), ColumnExpr(ColumnExpr), loc(loc) {}
+
+void DependentSizedMatrixType::Profile(llvm::FoldingSetNodeID &ID,
+ const ASTContext &CTX,
+ QualType ElementType, Expr *RowExpr,
+ Expr *ColumnExpr) {
+ ID.AddPointer(ElementType.getAsOpaquePtr());
+ RowExpr->Profile(ID, CTX, true);
+ ColumnExpr->Profile(ID, CTX, true);
+}
+
VectorType::VectorType(QualType vecType, unsigned nElements, QualType canonType,
VectorKind vecKind)
: VectorType(Vector, vecType, nElements, canonType, vecKind) {}
VectorType::VectorType(TypeClass tc, QualType vecType, unsigned nElements,
QualType canonType, VectorKind vecKind)
- : Type(tc, canonType, vecType->isDependentType(),
- vecType->isInstantiationDependentType(),
- vecType->isVariablyModifiedType(),
- vecType->containsUnexpandedParameterPack()),
- ElementType(vecType) {
+ : Type(tc, canonType, vecType->getDependence()), ElementType(vecType) {
VectorTypeBits.VecKind = vecKind;
VectorTypeBits.NumElements = nElements;
}
+ExtIntType::ExtIntType(bool IsUnsigned, unsigned NumBits)
+ : Type(ExtInt, QualType{}, TypeDependence::None), IsUnsigned(IsUnsigned),
+ NumBits(NumBits) {}
+
+DependentExtIntType::DependentExtIntType(const ASTContext &Context,
+ bool IsUnsigned, Expr *NumBitsExpr)
+ : Type(DependentExtInt, QualType{},
+ toTypeDependence(NumBitsExpr->getDependence())),
+ Context(Context), ExprAndUnsigned(NumBitsExpr, IsUnsigned) {}
+
+bool DependentExtIntType::isUnsigned() const {
+ return ExprAndUnsigned.getInt();
+}
+
+clang::Expr *DependentExtIntType::getNumBitsExpr() const {
+ return ExprAndUnsigned.getPointer();
+}
+
+void DependentExtIntType::Profile(llvm::FoldingSetNodeID &ID,
+ const ASTContext &Context, bool IsUnsigned,
+ Expr *NumBitsExpr) {
+ ID.AddBoolean(IsUnsigned);
+ NumBitsExpr->Profile(ID, Context, true);
+}
+
/// getArrayElementTypeNoTypeQual - If this is an array type, return the
/// element type of the array, potentially with type qualifiers missing.
/// This method should never be used when type qualifiers are meaningful.
@@ -652,14 +722,11 @@ bool Type::isObjCClassOrClassKindOfType() const {
return OPT->isObjCClassType() || OPT->isObjCQualifiedClassType();
}
-ObjCTypeParamType::ObjCTypeParamType(const ObjCTypeParamDecl *D,
- QualType can,
+ObjCTypeParamType::ObjCTypeParamType(const ObjCTypeParamDecl *D, QualType can,
ArrayRef<ObjCProtocolDecl *> protocols)
- : Type(ObjCTypeParam, can, can->isDependentType(),
- can->isInstantiationDependentType(),
- can->isVariablyModifiedType(),
- /*ContainsUnexpandedParameterPack=*/false),
- OTPDecl(const_cast<ObjCTypeParamDecl*>(D)) {
+ : Type(ObjCTypeParam, can,
+ can->getDependence() & ~TypeDependence::UnexpandedPack),
+ OTPDecl(const_cast<ObjCTypeParamDecl *>(D)) {
initialize(protocols);
}
@@ -667,11 +734,7 @@ ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
ArrayRef<QualType> typeArgs,
ArrayRef<ObjCProtocolDecl *> protocols,
bool isKindOf)
- : Type(ObjCObject, Canonical, Base->isDependentType(),
- Base->isInstantiationDependentType(),
- Base->isVariablyModifiedType(),
- Base->containsUnexpandedParameterPack()),
- BaseType(Base) {
+ : Type(ObjCObject, Canonical, Base->getDependence()), BaseType(Base) {
ObjCObjectTypeBits.IsKindOf = isKindOf;
ObjCObjectTypeBits.NumTypeArgs = typeArgs.size();
@@ -682,13 +745,7 @@ ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
typeArgs.size() * sizeof(QualType));
for (auto typeArg : typeArgs) {
- if (typeArg->isDependentType())
- setDependent();
- else if (typeArg->isInstantiationDependentType())
- setInstantiationDependent();
-
- if (typeArg->containsUnexpandedParameterPack())
- setContainsUnexpandedParameterPack();
+ addDependence(typeArg->getDependence() & ~TypeDependence::VariablyModified);
}
// Initialize the protocol qualifiers. The protocol storage is known
// after we set number of type arguments.
@@ -953,6 +1010,17 @@ public:
return Ctx.getExtVectorType(elementType, T->getNumElements());
}
+ QualType VisitConstantMatrixType(const ConstantMatrixType *T) {
+ QualType elementType = recurse(T->getElementType());
+ if (elementType.isNull())
+ return {};
+ if (elementType.getAsOpaquePtr() == T->getElementType().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getConstantMatrixType(elementType, T->getNumRows(),
+ T->getNumColumns());
+ }
+
QualType VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
QualType returnType = recurse(T->getReturnType());
if (returnType.isNull())
@@ -1114,7 +1182,9 @@ public:
return QualType(T, 0);
return Ctx.getAutoType(deducedType, T->getKeyword(),
- T->isDependentType());
+ T->isDependentType(), /*IsPack=*/false,
+ T->getTypeConstraintConcept(),
+ T->getTypeConstraintArguments());
}
// FIXME: Non-trivial to implement, but important for C++
@@ -1770,6 +1840,14 @@ namespace {
return Visit(T->getElementType());
}
+ Type *VisitDependentSizedMatrixType(const DependentSizedMatrixType *T) {
+ return Visit(T->getElementType());
+ }
+
+ Type *VisitConstantMatrixType(const ConstantMatrixType *T) {
+ return Visit(T->getElementType());
+ }
+
Type *VisitFunctionProtoType(const FunctionProtoType *T) {
if (Syntactic && T->hasTrailingReturn())
return const_cast<FunctionProtoType*>(T);
@@ -1849,13 +1927,17 @@ bool Type::isIntegralType(const ASTContext &Ctx) const {
if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
return ET->getDecl()->isComplete();
- return false;
+ return isExtIntType();
}
bool Type::isIntegralOrUnscopedEnumerationType() const {
if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::Int128;
+
+ if (isExtIntType())
+ return true;
+
return isUnscopedEnumerationType();
}
@@ -1936,6 +2018,9 @@ bool Type::isSignedIntegerType() const {
return ET->getDecl()->getIntegerType()->isSignedIntegerType();
}
+ if (const ExtIntType *IT = dyn_cast<ExtIntType>(CanonicalType))
+ return IT->isSigned();
+
return false;
}
@@ -1950,6 +2035,10 @@ bool Type::isSignedIntegerOrEnumerationType() const {
return ET->getDecl()->getIntegerType()->isSignedIntegerType();
}
+ if (const ExtIntType *IT = dyn_cast<ExtIntType>(CanonicalType))
+ return IT->isSigned();
+
+
return false;
}
@@ -1976,6 +2065,9 @@ bool Type::isUnsignedIntegerType() const {
return ET->getDecl()->getIntegerType()->isUnsignedIntegerType();
}
+ if (const ExtIntType *IT = dyn_cast<ExtIntType>(CanonicalType))
+ return IT->isUnsigned();
+
return false;
}
@@ -1990,6 +2082,9 @@ bool Type::isUnsignedIntegerOrEnumerationType() const {
return ET->getDecl()->getIntegerType()->isUnsignedIntegerType();
}
+ if (const ExtIntType *IT = dyn_cast<ExtIntType>(CanonicalType))
+ return IT->isUnsigned();
+
return false;
}
@@ -2028,13 +2123,14 @@ bool Type::isRealType() const {
BT->getKind() <= BuiltinType::Float128;
if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped();
- return false;
+ return isExtIntType();
}
bool Type::isArithmeticType() const {
if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
- BT->getKind() <= BuiltinType::Float128;
+ BT->getKind() <= BuiltinType::Float128 &&
+ BT->getKind() != BuiltinType::BFloat16;
if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
// GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2).
// If a body isn't seen by the time we get here, return false.
@@ -2043,7 +2139,7 @@ bool Type::isArithmeticType() const {
// false for scoped enumerations since that will disable any
// unwanted implicit conversions.
return !ET->getDecl()->isScoped() && ET->getDecl()->isComplete();
- return isa<ComplexType>(CanonicalType);
+ return isa<ComplexType>(CanonicalType) || isExtIntType();
}
Type::ScalarTypeKind Type::getScalarTypeKind() const {
@@ -2072,6 +2168,8 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const {
if (CT->getElementType()->isRealFloatingType())
return STK_FloatingComplex;
return STK_IntegralComplex;
+ } else if (isExtIntType()) {
+ return STK_Integral;
}
llvm_unreachable("unknown scalar type");
@@ -2180,6 +2278,22 @@ bool Type::isIncompleteType(NamedDecl **Def) const {
}
}
+bool Type::isSizelessBuiltinType() const {
+ if (const BuiltinType *BT = getAs<BuiltinType>()) {
+ switch (BT->getKind()) {
+ // SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/AArch64SVEACLETypes.def"
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+}
+
+bool Type::isSizelessType() const { return isSizelessBuiltinType(); }
+
bool QualType::isPODType(const ASTContext &Context) const {
// C++11 has a more relaxed definition of POD.
if (Context.getLangOpts().CPlusPlus11)
@@ -2221,6 +2335,7 @@ bool QualType::isCXX98PODType(const ASTContext &Context) const {
case Type::MemberPointer:
case Type::Vector:
case Type::ExtVector:
+ case Type::ExtInt:
return true;
case Type::Enum:
@@ -2246,6 +2361,9 @@ bool QualType::isTrivialType(const ASTContext &Context) const {
if ((*this)->isArrayType())
return Context.getBaseElementType(*this).isTrivialType(Context);
+ if ((*this)->isSizelessBuiltinType())
+ return true;
+
// Return false for incomplete types after skipping any incomplete array
// types which are expressly allowed by the standard and thus our API.
if ((*this)->isIncompleteType())
@@ -2300,6 +2418,9 @@ bool QualType::isTriviallyCopyableType(const ASTContext &Context) const {
if (CanonicalType->isDependentType())
return false;
+ if (CanonicalType->isSizelessBuiltinType())
+ return true;
+
// Return false for incomplete types after skipping any incomplete array types
// which are expressly allowed by the standard and thus our API.
if (CanonicalType->isIncompleteType())
@@ -2493,6 +2614,9 @@ bool QualType::isCXX11PODType(const ASTContext &Context) const {
const Type *BaseTy = ty->getBaseElementTypeUnsafe();
assert(BaseTy && "NULL element type");
+ if (BaseTy->isSizelessBuiltinType())
+ return true;
+
// Return false for incomplete types after skipping any incomplete array
// types which are expressly allowed by the standard and thus our API.
if (BaseTy->isIncompleteType())
@@ -2697,21 +2821,20 @@ StringRef TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) {
}
DependentTemplateSpecializationType::DependentTemplateSpecializationType(
- ElaboratedTypeKeyword Keyword,
- NestedNameSpecifier *NNS, const IdentifierInfo *Name,
- ArrayRef<TemplateArgument> Args,
- QualType Canon)
- : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true, true,
- /*VariablyModified=*/false,
- NNS && NNS->containsUnexpandedParameterPack()),
- NNS(NNS), Name(Name) {
+ ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
+ const IdentifierInfo *Name, ArrayRef<TemplateArgument> Args, QualType Canon)
+ : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon,
+ TypeDependence::DependentInstantiation |
+ (NNS ? toTypeDependence(NNS->getDependence())
+ : TypeDependence::None)),
+ NNS(NNS), Name(Name) {
DependentTemplateSpecializationTypeBits.NumArgs = Args.size();
assert((!NNS || NNS->isDependent()) &&
"DependentTemplateSpecializatonType requires dependent qualifier");
TemplateArgument *ArgBuffer = getArgBuffer();
for (const TemplateArgument &Arg : Args) {
- if (Arg.containsUnexpandedParameterPack())
- setContainsUnexpandedParameterPack();
+ addDependence(toTypeDependence(Arg.getDependence() &
+ TemplateArgumentDependence::UnexpandedPack));
new (ArgBuffer++) TemplateArgument(Arg);
}
@@ -2792,6 +2915,8 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
return "unsigned __int128";
case Half:
return Policy.Half ? "half" : "__fp16";
+ case BFloat16:
+ return "__bf16";
case Float:
return "float";
case Double:
@@ -2895,8 +3020,14 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
return "queue_t";
case OCLReserveID:
return "reserve_id_t";
+ case IncompleteMatrixIdx:
+ return "<incomplete matrix index type>";
case OMPArraySection:
return "<OpenMP array section type>";
+ case OMPArrayShaping:
+ return "<OpenMP array shaping type>";
+ case OMPIterator:
+ return "<OpenMP iterator type>";
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
case Id: \
return #ExtType;
@@ -2910,6 +3041,13 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
llvm_unreachable("Invalid builtin type.");
}
+QualType QualType::getNonPackExpansionType() const {
+ // We never wrap type sugar around a PackExpansionType.
+ if (auto *PET = dyn_cast<PackExpansionType>(getTypePtr()))
+ return PET->getPattern();
+ return *this;
+}
+
QualType QualType::getNonLValueExprType(const ASTContext &Context) const {
if (const auto *RefType = getTypePtr()->getAs<ReferenceType>())
return RefType->getPointeeType();
@@ -2954,10 +3092,8 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
QualType canonical,
const ExtProtoInfo &epi)
- : FunctionType(FunctionProto, result, canonical, result->isDependentType(),
- result->isInstantiationDependentType(),
- result->isVariablyModifiedType(),
- result->containsUnexpandedParameterPack(), epi.ExtInfo) {
+ : FunctionType(FunctionProto, result, canonical, result->getDependence(),
+ epi.ExtInfo) {
FunctionTypeBits.FastTypeQuals = epi.TypeQuals.getFastQualifiers();
FunctionTypeBits.RefQualifier = epi.RefQualifier;
FunctionTypeBits.NumParams = params.size();
@@ -2976,14 +3112,8 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
// Fill in the trailing argument array.
auto *argSlot = getTrailingObjects<QualType>();
for (unsigned i = 0; i != getNumParams(); ++i) {
- if (params[i]->isDependentType())
- setDependent();
- else if (params[i]->isInstantiationDependentType())
- setInstantiationDependent();
-
- if (params[i]->containsUnexpandedParameterPack())
- setContainsUnexpandedParameterPack();
-
+ addDependence(params[i]->getDependence() &
+ ~TypeDependence::VariablyModified);
argSlot[i] = params[i];
}
@@ -2997,11 +3127,9 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
// Note that, before C++17, a dependent exception specification does
// *not* make a type dependent; it's not even part of the C++ type
// system.
- if (ExceptionType->isInstantiationDependentType())
- setInstantiationDependent();
-
- if (ExceptionType->containsUnexpandedParameterPack())
- setContainsUnexpandedParameterPack();
+ addDependence(
+ ExceptionType->getDependence() &
+ (TypeDependence::Instantiation | TypeDependence::UnexpandedPack));
exnSlot[I++] = ExceptionType;
}
@@ -3015,12 +3143,9 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
// Store the noexcept expression and context.
*getTrailingObjects<Expr *>() = epi.ExceptionSpec.NoexceptExpr;
- if (epi.ExceptionSpec.NoexceptExpr->isValueDependent() ||
- epi.ExceptionSpec.NoexceptExpr->isInstantiationDependent())
- setInstantiationDependent();
-
- if (epi.ExceptionSpec.NoexceptExpr->containsUnexpandedParameterPack())
- setContainsUnexpandedParameterPack();
+ addDependence(
+ toTypeDependence(epi.ExceptionSpec.NoexceptExpr->getDependence()) &
+ (TypeDependence::Instantiation | TypeDependence::UnexpandedPack));
}
// Fill in the FunctionDecl * in the exception specification if present.
else if (getExceptionSpecType() == EST_Uninstantiated) {
@@ -3044,11 +3169,11 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
if (getExceptionSpecType() == EST_Dynamic ||
getExceptionSpecType() == EST_DependentNoexcept) {
assert(hasDependentExceptionSpec() && "type should not be canonical");
- setDependent();
+ addDependence(TypeDependence::DependentInstantiation);
}
} else if (getCanonicalTypeInternal()->isDependentType()) {
// Ask our canonical type whether our exception specification was dependent.
- setDependent();
+ addDependence(TypeDependence::DependentInstantiation);
}
// Fill in the extra parameter info if present.
@@ -3211,10 +3336,10 @@ QualType MacroQualifiedType::getModifiedType() const {
}
TypeOfExprType::TypeOfExprType(Expr *E, QualType can)
- : Type(TypeOfExpr, can, E->isTypeDependent(),
- E->isInstantiationDependent(),
- E->getType()->isVariablyModifiedType(),
- E->containsUnexpandedParameterPack()),
+ : Type(TypeOfExpr, can,
+ toTypeDependence(E->getDependence()) |
+ (E->getType()->getDependence() &
+ TypeDependence::VariablyModified)),
TOExpr(E) {}
bool TypeOfExprType::isSugared() const {
@@ -3234,13 +3359,15 @@ void DependentTypeOfExprType::Profile(llvm::FoldingSetNodeID &ID,
}
DecltypeType::DecltypeType(Expr *E, QualType underlyingType, QualType can)
- // C++11 [temp.type]p2: "If an expression e involves a template parameter,
- // decltype(e) denotes a unique dependent type." Hence a decltype type is
- // type-dependent even if its expression is only instantiation-dependent.
- : Type(Decltype, can, E->isInstantiationDependent(),
- E->isInstantiationDependent(),
- E->getType()->isVariablyModifiedType(),
- E->containsUnexpandedParameterPack()),
+ // C++11 [temp.type]p2: "If an expression e involves a template parameter,
+ // decltype(e) denotes a unique dependent type." Hence a decltype type is
+ // type-dependent even if its expression is only instantiation-dependent.
+ : Type(Decltype, can,
+ toTypeDependence(E->getDependence()) |
+ (E->isInstantiationDependent() ? TypeDependence::Dependent
+ : TypeDependence::None) |
+ (E->getType()->getDependence() &
+ TypeDependence::VariablyModified)),
E(E), UnderlyingType(underlyingType) {}
bool DecltypeType::isSugared() const { return !E->isInstantiationDependent(); }
@@ -3261,13 +3388,9 @@ void DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID,
}
UnaryTransformType::UnaryTransformType(QualType BaseType,
- QualType UnderlyingType,
- UTTKind UKind,
+ QualType UnderlyingType, UTTKind UKind,
QualType CanonicalType)
- : Type(UnaryTransform, CanonicalType, BaseType->isDependentType(),
- BaseType->isInstantiationDependentType(),
- BaseType->isVariablyModifiedType(),
- BaseType->containsUnexpandedParameterPack()),
+ : Type(UnaryTransform, CanonicalType, BaseType->getDependence()),
BaseType(BaseType), UnderlyingType(UnderlyingType), UKind(UKind) {}
DependentUnaryTransformType::DependentUnaryTransformType(const ASTContext &C,
@@ -3276,11 +3399,10 @@ DependentUnaryTransformType::DependentUnaryTransformType(const ASTContext &C,
: UnaryTransformType(BaseType, C.DependentTy, UKind, QualType()) {}
TagType::TagType(TypeClass TC, const TagDecl *D, QualType can)
- : Type(TC, can, D->isDependentType(),
- /*InstantiationDependent=*/D->isDependentType(),
- /*VariablyModified=*/false,
- /*ContainsUnexpandedParameterPack=*/false),
- decl(const_cast<TagDecl*>(D)) {}
+ : Type(TC, can,
+ D->isDependentType() ? TypeDependence::DependentInstantiation
+ : TypeDependence::None),
+ decl(const_cast<TagDecl *>(D)) {}
static TagDecl *getInterestingTagDecl(TagDecl *decl) {
for (auto I : decl->redecls()) {
@@ -3389,11 +3511,12 @@ IdentifierInfo *TemplateTypeParmType::getIdentifier() const {
return isCanonicalUnqualified() ? nullptr : getDecl()->getIdentifier();
}
-SubstTemplateTypeParmPackType::
-SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param,
- QualType Canon,
- const TemplateArgument &ArgPack)
- : Type(SubstTemplateTypeParmPack, Canon, true, true, false, true),
+SubstTemplateTypeParmPackType::SubstTemplateTypeParmPackType(
+ const TemplateTypeParmType *Param, QualType Canon,
+ const TemplateArgument &ArgPack)
+ : Type(SubstTemplateTypeParmPack, Canon,
+ TypeDependence::DependentInstantiation |
+ TypeDependence::UnexpandedPack),
Replaced(Param), Arguments(ArgPack.pack_begin()) {
SubstTemplateTypeParmPackTypeBits.NumArgs = ArgPack.pack_size();
}
@@ -3437,16 +3560,17 @@ anyDependentTemplateArguments(ArrayRef<TemplateArgumentLoc> Args,
return false;
}
-TemplateSpecializationType::
-TemplateSpecializationType(TemplateName T,
- ArrayRef<TemplateArgument> Args,
- QualType Canon, QualType AliasedType)
- : Type(TemplateSpecialization,
- Canon.isNull()? QualType(this, 0) : Canon,
- Canon.isNull()? true : Canon->isDependentType(),
- Canon.isNull()? true : Canon->isInstantiationDependentType(),
- false,
- T.containsUnexpandedParameterPack()), Template(T) {
+TemplateSpecializationType::TemplateSpecializationType(
+ TemplateName T, ArrayRef<TemplateArgument> Args, QualType Canon,
+ QualType AliasedType)
+ : Type(TemplateSpecialization, Canon.isNull() ? QualType(this, 0) : Canon,
+ (Canon.isNull()
+ ? TypeDependence::DependentInstantiation
+ : Canon->getDependence() & ~(TypeDependence::VariablyModified |
+ TypeDependence::UnexpandedPack)) |
+ (toTypeDependence(T.getDependence()) &
+ TypeDependence::UnexpandedPack)),
+ Template(T) {
TemplateSpecializationTypeBits.NumArgs = Args.size();
TemplateSpecializationTypeBits.TypeAlias = !AliasedType.isNull();
@@ -3459,7 +3583,7 @@ TemplateSpecializationType(TemplateName T,
auto *TemplateArgs = reinterpret_cast<TemplateArgument *>(this + 1);
for (const TemplateArgument &Arg : Args) {
- // Update instantiation-dependent and variably-modified bits.
+ // Update instantiation-dependent, variably-modified, and error bits.
// If the canonical type exists and is non-dependent, the template
// specialization type can be non-dependent even if one of the type
// arguments is. Given:
@@ -3467,13 +3591,11 @@ TemplateSpecializationType(TemplateName T,
// U<T> is always non-dependent, irrespective of the type T.
// However, U<Ts> contains an unexpanded parameter pack, even though
// its expansion (and thus its desugared type) doesn't.
- if (Arg.isInstantiationDependent())
- setInstantiationDependent();
- if (Arg.getKind() == TemplateArgument::Type &&
- Arg.getAsType()->isVariablyModifiedType())
- setVariablyModified();
- if (Arg.containsUnexpandedParameterPack())
- setContainsUnexpandedParameterPack();
+ addDependence(toTypeDependence(Arg.getDependence()) &
+ ~TypeDependence::Dependent);
+ if (Arg.getKind() == TemplateArgument::Type)
+ addDependence(Arg.getAsType()->getDependence() &
+ TypeDependence::VariablyModified);
new (TemplateArgs++) TemplateArgument(Arg);
}
@@ -3533,15 +3655,17 @@ void ObjCObjectTypeImpl::Profile(llvm::FoldingSetNodeID &ID) {
void ObjCTypeParamType::Profile(llvm::FoldingSetNodeID &ID,
const ObjCTypeParamDecl *OTPDecl,
+ QualType CanonicalType,
ArrayRef<ObjCProtocolDecl *> protocols) {
ID.AddPointer(OTPDecl);
+ ID.AddPointer(CanonicalType.getAsOpaquePtr());
ID.AddInteger(protocols.size());
for (auto proto : protocols)
ID.AddPointer(proto);
}
void ObjCTypeParamType::Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getDecl(),
+ Profile(ID, getDecl(), getCanonicalTypeInternal(),
llvm::makeArrayRef(qual_begin(), getNumProtocols()));
}
@@ -3644,6 +3768,7 @@ static CachedProperties computeCachedProperties(const Type *T) {
// here in error recovery.
return CachedProperties(ExternalLinkage, false);
+ case Type::ExtInt:
case Type::Builtin:
// C++ [basic.link]p8:
// A type is said to have linkage if and only if:
@@ -3689,6 +3814,8 @@ static CachedProperties computeCachedProperties(const Type *T) {
case Type::Vector:
case Type::ExtVector:
return Cache::get(cast<VectorType>(T)->getElementType());
+ case Type::ConstantMatrix:
+ return Cache::get(cast<ConstantMatrixType>(T)->getElementType());
case Type::FunctionNoProto:
return Cache::get(cast<FunctionType>(T)->getReturnType());
case Type::FunctionProto: {
@@ -3741,6 +3868,7 @@ LinkageInfo LinkageComputer::computeTypeLinkageInfo(const Type *T) {
assert(T->isInstantiationDependentType());
return LinkageInfo::external();
+ case Type::ExtInt:
case Type::Builtin:
return LinkageInfo::external();
@@ -3774,6 +3902,9 @@ LinkageInfo LinkageComputer::computeTypeLinkageInfo(const Type *T) {
case Type::Vector:
case Type::ExtVector:
return computeTypeLinkageInfo(cast<VectorType>(T)->getElementType());
+ case Type::ConstantMatrix:
+ return computeTypeLinkageInfo(
+ cast<ConstantMatrixType>(T)->getElementType());
case Type::FunctionNoProto:
return computeTypeLinkageInfo(cast<FunctionType>(T)->getReturnType());
case Type::FunctionProto: {
@@ -3918,7 +4049,10 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
#include "clang/Basic/AArch64SVEACLETypes.def"
case BuiltinType::BuiltinFn:
case BuiltinType::NullPtr:
+ case BuiltinType::IncompleteMatrixIdx:
case BuiltinType::OMPArraySection:
+ case BuiltinType::OMPArrayShaping:
+ case BuiltinType::OMPIterator:
return false;
}
llvm_unreachable("unknown builtin type");
@@ -3935,6 +4069,8 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
case Type::DependentSizedExtVector:
case Type::Vector:
case Type::ExtVector:
+ case Type::ConstantMatrix:
+ case Type::DependentSizedMatrix:
case Type::DependentAddressSpace:
case Type::FunctionProto:
case Type::FunctionNoProto:
@@ -3947,6 +4083,8 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
case Type::ObjCInterface:
case Type::Atomic:
case Type::Pipe:
+ case Type::ExtInt:
+ case Type::DependentExtInt:
return false;
}
llvm_unreachable("bad type kind!");
@@ -4098,6 +4236,20 @@ bool Type::isCARCBridgableType() const {
return Pointee->isVoidType() || Pointee->isRecordType();
}
+/// Check if the specified type is the CUDA device builtin surface type.
+bool Type::isCUDADeviceBuiltinSurfaceType() const {
+ if (const auto *RT = getAs<RecordType>())
+ return RT->getDecl()->hasAttr<CUDADeviceBuiltinSurfaceTypeAttr>();
+ return false;
+}
+
+/// Check if the specified type is the CUDA device builtin texture type.
+bool Type::isCUDADeviceBuiltinTextureType() const {
+ if (const auto *RT = getAs<RecordType>())
+ return RT->getDecl()->hasAttr<CUDADeviceBuiltinTextureTypeAttr>();
+ return false;
+}
+
bool Type::hasSizedVLAType() const {
if (!isVariablyModifiedType()) return false;
@@ -4158,3 +4310,34 @@ void clang::FixedPointValueToString(SmallVectorImpl<char> &Str,
/*HasUnsignedPadding=*/false);
APFixedPoint(Val, FXSema).toString(Str);
}
+
+AutoType::AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword,
+ TypeDependence ExtraDependence,
+ ConceptDecl *TypeConstraintConcept,
+ ArrayRef<TemplateArgument> TypeConstraintArgs)
+ : DeducedType(Auto, DeducedAsType, ExtraDependence) {
+ AutoTypeBits.Keyword = (unsigned)Keyword;
+ AutoTypeBits.NumArgs = TypeConstraintArgs.size();
+ this->TypeConstraintConcept = TypeConstraintConcept;
+ if (TypeConstraintConcept) {
+ TemplateArgument *ArgBuffer = getArgBuffer();
+ for (const TemplateArgument &Arg : TypeConstraintArgs) {
+ addDependence(toTypeDependence(
+ Arg.getDependence() & TemplateArgumentDependence::UnexpandedPack));
+
+ new (ArgBuffer++) TemplateArgument(Arg);
+ }
+ }
+}
+
+void AutoType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
+ QualType Deduced, AutoTypeKeyword Keyword,
+ bool IsDependent, ConceptDecl *CD,
+ ArrayRef<TemplateArgument> Arguments) {
+ ID.AddPointer(Deduced.getAsOpaquePtr());
+ ID.AddInteger((unsigned)Keyword);
+ ID.AddBoolean(IsDependent);
+ ID.AddPointer(CD);
+ for (const TemplateArgument &Arg : Arguments)
+ Arg.Profile(ID, Context);
+}
diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp
index 6e67ca8e0af72..57c11ca5571db 100644
--- a/clang/lib/AST/TypeLoc.cpp
+++ b/clang/lib/AST/TypeLoc.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/TypeLoc.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Expr.h"
@@ -374,6 +375,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
case BuiltinType::SatUShortFract:
case BuiltinType::SatUFract:
case BuiltinType::SatULongFract:
+ case BuiltinType::BFloat16:
llvm_unreachable("Builtin type needs extra local data!");
// Fall through, if the impossible happens.
@@ -402,7 +404,10 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
case BuiltinType::Id:
#include "clang/Basic/AArch64SVEACLETypes.def"
case BuiltinType::BuiltinFn:
+ case BuiltinType::IncompleteMatrixIdx:
case BuiltinType::OMPArraySection:
+ case BuiltinType::OMPArrayShaping:
+ case BuiltinType::OMPIterator:
return TST_unspecified;
}
@@ -589,3 +594,97 @@ void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
}
}
}
+
+DeclarationNameInfo AutoTypeLoc::getConceptNameInfo() const {
+ return DeclarationNameInfo(getNamedConcept()->getDeclName(),
+ getLocalData()->ConceptNameLoc);
+}
+
+void AutoTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setNestedNameSpecifierLoc(NestedNameSpecifierLoc());
+ setTemplateKWLoc(Loc);
+ setConceptNameLoc(Loc);
+ setFoundDecl(nullptr);
+ setRAngleLoc(Loc);
+ setLAngleLoc(Loc);
+ TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
+ getTypePtr()->getArgs(),
+ getArgInfos(), Loc);
+ setNameLoc(Loc);
+}
+
+
+namespace {
+
+ class GetContainedAutoTypeLocVisitor :
+ public TypeLocVisitor<GetContainedAutoTypeLocVisitor, TypeLoc> {
+ public:
+ using TypeLocVisitor<GetContainedAutoTypeLocVisitor, TypeLoc>::Visit;
+
+ TypeLoc VisitAutoTypeLoc(AutoTypeLoc TL) {
+ return TL;
+ }
+
+ // Only these types can contain the desired 'auto' type.
+
+ TypeLoc VisitElaboratedTypeLoc(ElaboratedTypeLoc T) {
+ return Visit(T.getNamedTypeLoc());
+ }
+
+ TypeLoc VisitQualifiedTypeLoc(QualifiedTypeLoc T) {
+ return Visit(T.getUnqualifiedLoc());
+ }
+
+ TypeLoc VisitPointerTypeLoc(PointerTypeLoc T) {
+ return Visit(T.getPointeeLoc());
+ }
+
+ TypeLoc VisitBlockPointerTypeLoc(BlockPointerTypeLoc T) {
+ return Visit(T.getPointeeLoc());
+ }
+
+ TypeLoc VisitReferenceTypeLoc(ReferenceTypeLoc T) {
+ return Visit(T.getPointeeLoc());
+ }
+
+ TypeLoc VisitMemberPointerTypeLoc(MemberPointerTypeLoc T) {
+ return Visit(T.getPointeeLoc());
+ }
+
+ TypeLoc VisitArrayTypeLoc(ArrayTypeLoc T) {
+ return Visit(T.getElementLoc());
+ }
+
+ TypeLoc VisitFunctionTypeLoc(FunctionTypeLoc T) {
+ return Visit(T.getReturnLoc());
+ }
+
+ TypeLoc VisitParenTypeLoc(ParenTypeLoc T) {
+ return Visit(T.getInnerLoc());
+ }
+
+ TypeLoc VisitAttributedTypeLoc(AttributedTypeLoc T) {
+ return Visit(T.getModifiedLoc());
+ }
+
+ TypeLoc VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc T) {
+ return Visit(T.getInnerLoc());
+ }
+
+ TypeLoc VisitAdjustedTypeLoc(AdjustedTypeLoc T) {
+ return Visit(T.getOriginalLoc());
+ }
+
+ TypeLoc VisitPackExpansionTypeLoc(PackExpansionTypeLoc T) {
+ return Visit(T.getPatternLoc());
+ }
+ };
+
+} // namespace
+
+AutoTypeLoc TypeLoc::getContainedAutoTypeLoc() const {
+ TypeLoc Res = GetContainedAutoTypeLocVisitor().Visit(*this);
+ if (Res.isNull())
+ return AutoTypeLoc();
+ return Res.getAs<AutoTypeLoc>();
+}
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index c2f4baec989ee..6f6932e652146 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -227,6 +227,8 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
case Type::ObjCInterface:
case Type::Atomic:
case Type::Pipe:
+ case Type::ExtInt:
+ case Type::DependentExtInt:
CanPrefixQualifiers = true;
break;
@@ -254,6 +256,8 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
case Type::DependentSizedExtVector:
case Type::Vector:
case Type::ExtVector:
+ case Type::ConstantMatrix:
+ case Type::DependentSizedMatrix:
case Type::FunctionProto:
case Type::FunctionNoProto:
case Type::Paren:
@@ -718,6 +722,38 @@ void TypePrinter::printExtVectorAfter(const ExtVectorType *T, raw_ostream &OS) {
OS << ")))";
}
+void TypePrinter::printConstantMatrixBefore(const ConstantMatrixType *T,
+ raw_ostream &OS) {
+ printBefore(T->getElementType(), OS);
+ OS << " __attribute__((matrix_type(";
+ OS << T->getNumRows() << ", " << T->getNumColumns();
+ OS << ")))";
+}
+
+void TypePrinter::printConstantMatrixAfter(const ConstantMatrixType *T,
+ raw_ostream &OS) {
+ printAfter(T->getElementType(), OS);
+}
+
+void TypePrinter::printDependentSizedMatrixBefore(
+ const DependentSizedMatrixType *T, raw_ostream &OS) {
+ printBefore(T->getElementType(), OS);
+ OS << " __attribute__((matrix_type(";
+ if (T->getRowExpr()) {
+ T->getRowExpr()->printPretty(OS, nullptr, Policy);
+ }
+ OS << ", ";
+ if (T->getColumnExpr()) {
+ T->getColumnExpr()->printPretty(OS, nullptr, Policy);
+ }
+ OS << ")))";
+}
+
+void TypePrinter::printDependentSizedMatrixAfter(
+ const DependentSizedMatrixType *T, raw_ostream &OS) {
+ printAfter(T->getElementType(), OS);
+}
+
void
FunctionProtoType::printExceptionSpecification(raw_ostream &OS,
const PrintingPolicy &Policy)
@@ -909,6 +945,8 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info,
if (Info.getNoReturn())
OS << " __attribute__((noreturn))";
+ if (Info.getCmseNSCall())
+ OS << " __attribute__((cmse_nonsecure_call))";
if (Info.getProducesResult())
OS << " __attribute__((ns_returns_retained))";
if (Info.getRegParm())
@@ -1046,6 +1084,13 @@ void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) {
if (!T->getDeducedType().isNull()) {
printBefore(T->getDeducedType(), OS);
} else {
+ if (T->isConstrained()) {
+ OS << T->getTypeConstraintConcept()->getName();
+ auto Args = T->getTypeConstraintArguments();
+ if (!Args.empty())
+ printTemplateArgumentList(OS, Args, Policy);
+ OS << ' ';
+ }
switch (T->getKeyword()) {
case AutoTypeKeyword::Auto: OS << "auto"; break;
case AutoTypeKeyword::DecltypeAuto: OS << "decltype(auto)"; break;
@@ -1105,6 +1150,28 @@ void TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) {
void TypePrinter::printPipeAfter(const PipeType *T, raw_ostream &OS) {}
+void TypePrinter::printExtIntBefore(const ExtIntType *T, raw_ostream &OS) {
+ if (T->isUnsigned())
+ OS << "unsigned ";
+ OS << "_ExtInt(" << T->getNumBits() << ")";
+ spaceBeforePlaceHolder(OS);
+}
+
+void TypePrinter::printExtIntAfter(const ExtIntType *T, raw_ostream &OS) {}
+
+void TypePrinter::printDependentExtIntBefore(const DependentExtIntType *T,
+ raw_ostream &OS) {
+ if (T->isUnsigned())
+ OS << "unsigned ";
+ OS << "_ExtInt(";
+ T->getNumBitsExpr()->printPretty(OS, nullptr, Policy);
+ OS << ")";
+ spaceBeforePlaceHolder(OS);
+}
+
+void TypePrinter::printDependentExtIntAfter(const DependentExtIntType *T,
+ raw_ostream &OS) {}
+
/// Appends the given scope to the end of a string.
void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) {
if (DC->isTranslationUnit()) return;
@@ -1234,20 +1301,18 @@ void TypePrinter::printEnumAfter(const EnumType *T, raw_ostream &OS) {}
void TypePrinter::printTemplateTypeParmBefore(const TemplateTypeParmType *T,
raw_ostream &OS) {
- if (IdentifierInfo *Id = T->getIdentifier())
- OS << Id->getName();
- else {
- bool IsLambdaAutoParam = false;
- if (auto D = T->getDecl()) {
- if (auto M = dyn_cast_or_null<CXXMethodDecl>(D->getDeclContext()))
- IsLambdaAutoParam = D->isImplicit() && M->getParent()->isLambda();
+ TemplateTypeParmDecl *D = T->getDecl();
+ if (D && D->isImplicit()) {
+ if (auto *TC = D->getTypeConstraint()) {
+ TC->print(OS, Policy);
+ OS << ' ';
}
+ OS << "auto";
+ } else if (IdentifierInfo *Id = T->getIdentifier())
+ OS << Id->getName();
+ else
+ OS << "type-parameter-" << T->getDepth() << '-' << T->getIndex();
- if (IsLambdaAutoParam)
- OS << "auto";
- else
- OS << "type-parameter-" << T->getDepth() << '-' << T->getIndex();
- }
spaceBeforePlaceHolder(OS);
}
@@ -1298,7 +1363,12 @@ void TypePrinter::printTemplateSpecializationAfter(
void TypePrinter::printInjectedClassNameBefore(const InjectedClassNameType *T,
raw_ostream &OS) {
- printTemplateSpecializationBefore(T->getInjectedTST(), OS);
+ if (Policy.PrintInjectedClassNameWithArguments)
+ return printTemplateSpecializationBefore(T->getInjectedTST(), OS);
+
+ IncludeStrongLifetimeRAII Strong(Policy);
+ T->getTemplateName().print(OS, Policy);
+ spaceBeforePlaceHolder(OS);
}
void TypePrinter::printInjectedClassNameAfter(const InjectedClassNameType *T,
@@ -1381,7 +1451,7 @@ void TypePrinter::printDependentTemplateSpecializationBefore(
if (T->getQualifier())
T->getQualifier()->print(OS, Policy);
- OS << T->getIdentifier()->getName();
+ OS << "template " << T->getIdentifier()->getName();
printTemplateArgumentList(OS, T->template_arguments(), Policy);
spaceBeforePlaceHolder(OS);
}
@@ -1514,6 +1584,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
case attr::SPtr:
case attr::UPtr:
case attr::AddressSpace:
+ case attr::CmseNSCall:
llvm_unreachable("This attribute should have been handled already");
case attr::NSReturnsRetained:
@@ -1558,6 +1629,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
case attr::AcquireHandle:
OS << "acquire_handle";
break;
+ case attr::ArmMveStrictPolymorphism:
+ OS << "__clang_arm_mve_strict_polymorphism";
+ break;
}
OS << "))";
}
@@ -1711,13 +1785,13 @@ static void printTo(raw_ostream &OS, ArrayRef<TA> Args,
OS << ArgString;
- NeedSpace = (!ArgString.empty() && ArgString.back() == '>');
+ // If the last character of our string is '>', add another space to
+ // keep the two '>''s separate tokens.
+ NeedSpace = Policy.SplitTemplateClosers && !ArgString.empty() &&
+ ArgString.back() == '>';
FirstArg = false;
}
- // If the last character of our string is '>', add another space to
- // keep the two '>''s separate tokens. We don't *have* to do this in
- // C++0x, but it's still good hygiene.
if (NeedSpace)
OS << ' ';
@@ -1755,7 +1829,7 @@ std::string Qualifiers::getAsString(const PrintingPolicy &Policy) const {
SmallString<64> Buf;
llvm::raw_svector_ostream StrOS(Buf);
print(StrOS, Policy);
- return StrOS.str();
+ return std::string(StrOS.str());
}
bool Qualifiers::isEmptyWhenPrinted(const PrintingPolicy &Policy) const {
@@ -1913,6 +1987,6 @@ void QualType::getAsStringInternal(const Type *ty, Qualifiers qs,
SmallString<256> Buf;
llvm::raw_svector_ostream StrOS(Buf);
TypePrinter(policy).print(ty, qs, StrOS, buffer);
- std::string str = StrOS.str();
+ std::string str = std::string(StrOS.str());
buffer.swap(str);
}
diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp
index 2b5b74be5961c..f5865ce96b647 100644
--- a/clang/lib/AST/VTableBuilder.cpp
+++ b/clang/lib/AST/VTableBuilder.cpp
@@ -408,7 +408,7 @@ void FinalOverriders::dump(raw_ostream &Out, BaseSubobject Base,
// Now dump the overriders for this base subobject.
for (const auto *MD : RD->methods()) {
- if (!MD->isVirtual())
+ if (!VTableContextBase::hasVtableSlot(MD))
continue;
MD = MD->getCanonicalDecl();
@@ -486,8 +486,8 @@ static bool HasSameVirtualSignature(const CXXMethodDecl *LHS,
bool VCallOffsetMap::MethodsCanShareVCallOffset(const CXXMethodDecl *LHS,
const CXXMethodDecl *RHS) {
- assert(LHS->isVirtual() && "LHS must be virtual!");
- assert(RHS->isVirtual() && "LHS must be virtual!");
+ assert(VTableContextBase::hasVtableSlot(LHS) && "LHS must be virtual!");
+ assert(VTableContextBase::hasVtableSlot(RHS) && "LHS must be virtual!");
// A destructor can share a vcall offset with another destructor.
if (isa<CXXDestructorDecl>(LHS))
@@ -535,6 +535,8 @@ public:
VBaseOffsetOffsetsMapTy;
private:
+ const ItaniumVTableContext &VTables;
+
/// MostDerivedClass - The most derived class for which we're building vcall
/// and vbase offsets.
const CXXRecordDecl *MostDerivedClass;
@@ -583,13 +585,15 @@ private:
CharUnits getCurrentOffsetOffset() const;
public:
- VCallAndVBaseOffsetBuilder(const CXXRecordDecl *MostDerivedClass,
+ VCallAndVBaseOffsetBuilder(const ItaniumVTableContext &VTables,
+ const CXXRecordDecl *MostDerivedClass,
const CXXRecordDecl *LayoutClass,
const FinalOverriders *Overriders,
BaseSubobject Base, bool BaseIsVirtual,
CharUnits OffsetInLayoutClass)
- : MostDerivedClass(MostDerivedClass), LayoutClass(LayoutClass),
- Context(MostDerivedClass->getASTContext()), Overriders(Overriders) {
+ : VTables(VTables), MostDerivedClass(MostDerivedClass),
+ LayoutClass(LayoutClass), Context(MostDerivedClass->getASTContext()),
+ Overriders(Overriders) {
// Add vcall and vbase offsets.
AddVCallAndVBaseOffsets(Base, BaseIsVirtual, OffsetInLayoutClass);
@@ -662,9 +666,13 @@ CharUnits VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset() const {
// vcall offset itself).
int64_t OffsetIndex = -(int64_t)(3 + Components.size());
- CharUnits PointerWidth =
- Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
- CharUnits OffsetOffset = PointerWidth * OffsetIndex;
+ // Under the relative ABI, the offset widths are 32-bit ints instead of
+ // pointer widths.
+ CharUnits OffsetWidth = Context.toCharUnitsFromBits(
+ VTables.isRelativeLayout() ? 32
+ : Context.getTargetInfo().getPointerWidth(0));
+ CharUnits OffsetOffset = OffsetWidth * OffsetIndex;
+
return OffsetOffset;
}
@@ -689,7 +697,7 @@ void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
// Add the vcall offsets.
for (const auto *MD : RD->methods()) {
- if (!MD->isVirtual())
+ if (!VTableContextBase::hasVtableSlot(MD))
continue;
MD = MD->getCanonicalDecl();
@@ -1077,7 +1085,7 @@ typedef llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverriddenMethodsSetTy;
template <class VisitorTy>
static void
visitAllOverriddenMethods(const CXXMethodDecl *MD, VisitorTy &Visitor) {
- assert(MD->isVirtual() && "Method is not virtual!");
+ assert(VTableContextBase::hasVtableSlot(MD) && "Method is not virtual!");
for (const CXXMethodDecl *OverriddenMD : MD->overridden_methods()) {
if (!Visitor(OverriddenMD))
@@ -1271,13 +1279,13 @@ ThisAdjustment ItaniumVTableBuilder::ComputeThisAdjustment(
if (VCallOffsets.empty()) {
// We don't have vcall offsets for this virtual base, go ahead and
// build them.
- VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, MostDerivedClass,
- /*Overriders=*/nullptr,
- BaseSubobject(Offset.VirtualBase,
- CharUnits::Zero()),
- /*BaseIsVirtual=*/true,
- /*OffsetInLayoutClass=*/
- CharUnits::Zero());
+ VCallAndVBaseOffsetBuilder Builder(
+ VTables, MostDerivedClass, MostDerivedClass,
+ /*Overriders=*/nullptr,
+ BaseSubobject(Offset.VirtualBase, CharUnits::Zero()),
+ /*BaseIsVirtual=*/true,
+ /*OffsetInLayoutClass=*/
+ CharUnits::Zero());
VCallOffsets = Builder.getVCallOffsets();
}
@@ -1474,14 +1482,14 @@ void ItaniumVTableBuilder::AddMethods(
llvm_unreachable("Found a duplicate primary base!");
}
- const CXXDestructorDecl *ImplicitVirtualDtor = nullptr;
-
typedef llvm::SmallVector<const CXXMethodDecl *, 8> NewVirtualFunctionsTy;
NewVirtualFunctionsTy NewVirtualFunctions;
+ llvm::SmallVector<const CXXMethodDecl*, 4> NewImplicitVirtualFunctions;
+
// Now go through all virtual member functions and add them.
for (const auto *MD : RD->methods()) {
- if (!MD->isVirtual())
+ if (!ItaniumVTableContext::hasVtableSlot(MD))
continue;
MD = MD->getCanonicalDecl();
@@ -1542,24 +1550,30 @@ void ItaniumVTableBuilder::AddMethods(
}
}
- if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
- if (MD->isImplicit()) {
- // Itanium C++ ABI 2.5.2:
- // If a class has an implicitly-defined virtual destructor,
- // its entries come after the declared virtual function pointers.
-
- assert(!ImplicitVirtualDtor &&
- "Did already see an implicit virtual dtor!");
- ImplicitVirtualDtor = DD;
- continue;
- }
- }
-
- NewVirtualFunctions.push_back(MD);
- }
-
- if (ImplicitVirtualDtor)
- NewVirtualFunctions.push_back(ImplicitVirtualDtor);
+ if (MD->isImplicit())
+ NewImplicitVirtualFunctions.push_back(MD);
+ else
+ NewVirtualFunctions.push_back(MD);
+ }
+
+ std::stable_sort(
+ NewImplicitVirtualFunctions.begin(), NewImplicitVirtualFunctions.end(),
+ [](const CXXMethodDecl *A, const CXXMethodDecl *B) {
+ if (A->isCopyAssignmentOperator() != B->isCopyAssignmentOperator())
+ return A->isCopyAssignmentOperator();
+ if (A->isMoveAssignmentOperator() != B->isMoveAssignmentOperator())
+ return A->isMoveAssignmentOperator();
+ if (isa<CXXDestructorDecl>(A) != isa<CXXDestructorDecl>(B))
+ return isa<CXXDestructorDecl>(A);
+ assert(A->getOverloadedOperator() == OO_EqualEqual &&
+ B->getOverloadedOperator() == OO_EqualEqual &&
+ "unexpected or duplicate implicit virtual function");
+ // We rely on Sema to have declared the operator== members in the
+ // same order as the corresponding operator<=> members.
+ return false;
+ });
+ NewVirtualFunctions.append(NewImplicitVirtualFunctions.begin(),
+ NewImplicitVirtualFunctions.end());
for (const CXXMethodDecl *MD : NewVirtualFunctions) {
// Get the final overrider.
@@ -1629,9 +1643,9 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
VTableIndices.push_back(VTableIndex);
// Add vcall and vbase offsets for this vtable.
- VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, LayoutClass, &Overriders,
- Base, BaseIsVirtualInLayoutClass,
- OffsetInLayoutClass);
+ VCallAndVBaseOffsetBuilder Builder(
+ VTables, MostDerivedClass, LayoutClass, &Overriders, Base,
+ BaseIsVirtualInLayoutClass, OffsetInLayoutClass);
Components.append(Builder.components_begin(), Builder.components_end());
// Check if we need to add these vcall offsets.
@@ -2155,7 +2169,7 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
for (const auto *MD : MostDerivedClass->methods()) {
// We only want virtual member functions.
- if (!MD->isVirtual())
+ if (!ItaniumVTableContext::hasVtableSlot(MD))
continue;
MD = MD->getCanonicalDecl();
@@ -2194,12 +2208,40 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
}
}
+static VTableLayout::AddressPointsIndexMapTy
+MakeAddressPointIndices(const VTableLayout::AddressPointsMapTy &addressPoints,
+ unsigned numVTables) {
+ VTableLayout::AddressPointsIndexMapTy indexMap(numVTables);
+
+ for (auto it = addressPoints.begin(); it != addressPoints.end(); ++it) {
+ const auto &addressPointLoc = it->second;
+ unsigned vtableIndex = addressPointLoc.VTableIndex;
+ unsigned addressPoint = addressPointLoc.AddressPointIndex;
+ if (indexMap[vtableIndex]) {
+ // Multiple BaseSubobjects can map to the same AddressPointLocation, but
+ // every vtable index should have a unique address point.
+ assert(indexMap[vtableIndex] == addressPoint &&
+ "Every vtable index should have a unique address point. Found a "
+ "vtable that has two different address points.");
+ } else {
+ indexMap[vtableIndex] = addressPoint;
+ }
+ }
+
+ // Note that by this point, not all the address may be initialized if the
+ // AddressPoints map is empty. This is ok if the map isn't needed. See
+ // MicrosoftVTableContext::computeVTableRelatedInformation() which uses an
+ // emprt map.
+ return indexMap;
+}
+
VTableLayout::VTableLayout(ArrayRef<size_t> VTableIndices,
ArrayRef<VTableComponent> VTableComponents,
ArrayRef<VTableThunkTy> VTableThunks,
const AddressPointsMapTy &AddressPoints)
: VTableComponents(VTableComponents), VTableThunks(VTableThunks),
- AddressPoints(AddressPoints) {
+ AddressPoints(AddressPoints), AddressPointIndices(MakeAddressPointIndices(
+ AddressPoints, VTableIndices.size())) {
if (VTableIndices.size() <= 1)
assert(VTableIndices.size() == 1 && VTableIndices[0] == 0);
else
@@ -2215,8 +2257,13 @@ VTableLayout::VTableLayout(ArrayRef<size_t> VTableIndices,
VTableLayout::~VTableLayout() { }
-ItaniumVTableContext::ItaniumVTableContext(ASTContext &Context)
- : VTableContextBase(/*MS=*/false) {}
+bool VTableContextBase::hasVtableSlot(const CXXMethodDecl *MD) {
+ return MD->isVirtual() && !MD->isConsteval();
+}
+
+ItaniumVTableContext::ItaniumVTableContext(
+ ASTContext &Context, VTableComponentLayout ComponentLayout)
+ : VTableContextBase(/*MS=*/false), ComponentLayout(ComponentLayout) {}
ItaniumVTableContext::~ItaniumVTableContext() {}
@@ -2245,7 +2292,7 @@ ItaniumVTableContext::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
if (I != VirtualBaseClassOffsetOffsets.end())
return I->second;
- VCallAndVBaseOffsetBuilder Builder(RD, RD, /*Overriders=*/nullptr,
+ VCallAndVBaseOffsetBuilder Builder(*this, RD, RD, /*Overriders=*/nullptr,
BaseSubobject(RD, CharUnits::Zero()),
/*BaseIsVirtual=*/false,
/*OffsetInLayoutClass=*/CharUnits::Zero());
@@ -2494,8 +2541,9 @@ private:
BasesSetVectorTy VisitedBases;
AddMethods(BaseSubobject(MostDerivedClass, CharUnits::Zero()), 0, nullptr,
VisitedBases);
- assert((HasRTTIComponent ? Components.size() - 1 : Components.size()) &&
- "vftable can't be empty");
+ // Note that it is possible for the vftable to contain only an RTTI
+ // pointer, if all virtual functions are constewval.
+ assert(!Components.empty() && "vftable can't be empty");
assert(MethodVFTableLocations.empty());
for (const auto &I : MethodInfoMap) {
@@ -2874,7 +2922,7 @@ static void GroupNewVirtualOverloads(
if (Inserted)
Groups.push_back(MethodGroup());
if (const auto *MD = dyn_cast<CXXMethodDecl>(ND))
- if (MD->isVirtual())
+ if (MicrosoftVTableContext::hasVtableSlot(MD))
Groups[J->second].push_back(MD->getCanonicalDecl());
}
@@ -3470,7 +3518,7 @@ static const FullPathTy *selectBestPath(ASTContext &Context,
getOffsetOfFullPath(Context, TopLevelRD, SpecificPath);
FinalOverriders Overriders(TopLevelRD, CharUnits::Zero(), TopLevelRD);
for (const CXXMethodDecl *MD : Info.IntroducingObject->methods()) {
- if (!MD->isVirtual())
+ if (!MicrosoftVTableContext::hasVtableSlot(MD))
continue;
FinalOverriders::OverriderInfo OI =
Overriders.getOverrider(MD->getCanonicalDecl(), BaseOffset);
@@ -3609,7 +3657,7 @@ void MicrosoftVTableContext::dumpMethodLocations(
for (const auto &I : NewMethods) {
const CXXMethodDecl *MD = cast<const CXXMethodDecl>(I.first.getDecl());
- assert(MD->isVirtual());
+ assert(hasVtableSlot(MD));
std::string MethodName = PredefinedExpr::ComputeName(
PredefinedExpr::PrettyFunctionNoVirtual, MD);
@@ -3729,7 +3777,7 @@ MicrosoftVTableContext::getVFTableLayout(const CXXRecordDecl *RD,
MethodVFTableLocation
MicrosoftVTableContext::getMethodVFTableLocation(GlobalDecl GD) {
- assert(cast<CXXMethodDecl>(GD.getDecl())->isVirtual() &&
+ assert(hasVtableSlot(cast<CXXMethodDecl>(GD.getDecl())) &&
"Only use this method for virtual methods or dtors");
if (isa<CXXDestructorDecl>(GD.getDecl()))
assert(GD.getDtorType() == Dtor_Deleting);