diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
commit | cfca06d7963fa0909f90483b42a6d7d194d01e08 (patch) | |
tree | 209fb2a2d68f8f277793fc8df46c753d31bc853b /clang/lib/AST | |
parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff) |
Notes
Diffstat (limited to 'clang/lib/AST')
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 ⤅ - 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 ⤅ + 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); |