From cfca06d7963fa0909f90483b42a6d7d194d01e08 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sun, 26 Jul 2020 19:36:28 +0000 Subject: Vendor import of llvm-project master 2e10b7a39b9, the last commit before the llvmorg-12-init tag, from which release/11.x was branched. --- clang/lib/AST/APValue.cpp | 84 -- clang/lib/AST/ASTConcept.cpp | 13 + clang/lib/AST/ASTContext.cpp | 940 +++++++----- clang/lib/AST/ASTDiagnostic.cpp | 5 +- clang/lib/AST/ASTDumper.cpp | 95 +- clang/lib/AST/ASTImporter.cpp | 2152 ++++++++++++++-------------- clang/lib/AST/ASTImporterLookupTable.cpp | 6 +- clang/lib/AST/ASTStructuralEquivalence.cpp | 84 +- clang/lib/AST/ASTTypeTraits.cpp | 34 +- clang/lib/AST/AttrImpl.cpp | 151 ++ clang/lib/AST/CXXInheritance.cpp | 26 +- clang/lib/AST/CommentCommandTraits.cpp | 1 + clang/lib/AST/CommentSema.cpp | 50 +- clang/lib/AST/ComparisonCategories.cpp | 1 + clang/lib/AST/ComputeDependence.cpp | 796 ++++++++++ clang/lib/AST/DataCollection.cpp | 2 +- clang/lib/AST/Decl.cpp | 146 +- clang/lib/AST/DeclBase.cpp | 67 +- clang/lib/AST/DeclCXX.cpp | 268 +++- clang/lib/AST/DeclObjC.cpp | 29 +- clang/lib/AST/DeclPrinter.cpp | 131 +- clang/lib/AST/DeclTemplate.cpp | 52 +- clang/lib/AST/DeclarationName.cpp | 16 +- clang/lib/AST/Expr.cpp | 1164 +++++++++------ clang/lib/AST/ExprCXX.cpp | 488 +++---- clang/lib/AST/ExprClassification.cpp | 14 +- clang/lib/AST/ExprConcepts.cpp | 215 +++ clang/lib/AST/ExprConstant.cpp | 864 ++++++++--- clang/lib/AST/ExprObjC.cpp | 61 +- clang/lib/AST/ExternalASTSource.cpp | 19 +- clang/lib/AST/FormatString.cpp | 3 +- clang/lib/AST/Interp/Block.cpp | 87 -- clang/lib/AST/Interp/Block.h | 140 -- clang/lib/AST/Interp/Boolean.h | 7 +- clang/lib/AST/Interp/ByteCodeExprGen.h | 1 + clang/lib/AST/Interp/Context.cpp | 1 + clang/lib/AST/Interp/Disasm.cpp | 1 + clang/lib/AST/Interp/Integral.h | 33 +- clang/lib/AST/Interp/Interp.cpp | 2 +- clang/lib/AST/Interp/Interp.h | 2 +- clang/lib/AST/Interp/InterpBlock.cpp | 87 ++ clang/lib/AST/Interp/InterpBlock.h | 140 ++ clang/lib/AST/Interp/InterpFrame.h | 8 +- clang/lib/AST/Interp/Pointer.cpp | 2 +- clang/lib/AST/Interp/Pointer.h | 4 +- clang/lib/AST/Interp/Source.h | 4 +- clang/lib/AST/ItaniumMangle.cpp | 373 +++-- clang/lib/AST/JSONNodeDumper.cpp | 91 +- clang/lib/AST/Linkage.h | 1 + clang/lib/AST/Mangle.cpp | 74 +- clang/lib/AST/MicrosoftMangle.cpp | 170 ++- clang/lib/AST/NSAPI.cpp | 4 + clang/lib/AST/NestedNameSpecifier.cpp | 89 +- clang/lib/AST/ODRHash.cpp | 15 +- clang/lib/AST/OSLog.cpp | 6 +- clang/lib/AST/OpenMPClause.cpp | 655 ++++++++- clang/lib/AST/ParentMapContext.cpp | 321 +++++ clang/lib/AST/PrintfFormatString.cpp | 4 +- clang/lib/AST/RawCommentList.cpp | 3 +- clang/lib/AST/RecordLayoutBuilder.cpp | 38 +- clang/lib/AST/Stmt.cpp | 19 +- clang/lib/AST/StmtOpenMP.cpp | 101 +- clang/lib/AST/StmtPrinter.cpp | 200 ++- clang/lib/AST/StmtProfile.cpp | 152 +- clang/lib/AST/TemplateBase.cpp | 142 +- clang/lib/AST/TemplateName.cpp | 70 +- clang/lib/AST/TextNodeDumper.cpp | 407 +++++- clang/lib/AST/Type.cpp | 479 +++++-- clang/lib/AST/TypeLoc.cpp | 99 ++ clang/lib/AST/TypePrinter.cpp | 114 +- clang/lib/AST/VTableBuilder.cpp | 154 +- 71 files changed, 8245 insertions(+), 4032 deletions(-) create mode 100644 clang/lib/AST/ComputeDependence.cpp create mode 100644 clang/lib/AST/ExprConcepts.cpp delete mode 100644 clang/lib/AST/Interp/Block.cpp delete mode 100644 clang/lib/AST/Interp/Block.h create mode 100644 clang/lib/AST/Interp/InterpBlock.cpp create mode 100644 clang/lib/AST/Interp/InterpBlock.h create mode 100644 clang/lib/AST/ParentMapContext.cpp (limited to 'clang/lib/AST') diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index 50f8d05dacb4..f3828bb54c1d 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: "; - 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: "; - return; - case AddrLabelDiff: - OS << "AddrLabelDiff: "; - 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 fc32e768d92f..549088ad4a8a 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 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 a51429264dbe..2ba643f12a82 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(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()) { - 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 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 struct S {}; - the + // converted arguments of C could be an argument pack if C is + // declared as template 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(IDC)) + CSE = cast(Fold->getLHS()); + else + CSE = cast(IDC); + ArrayRef OldConverted = CSE->getTemplateArguments(); + SmallVector NewConverted; + NewConverted.reserve(OldConverted.size()); + if (OldConverted.front().getKind() == TemplateArgument::Pack) { + // The case: + // template concept C = true; + // template 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(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(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 struct S {}; - the - // converted arguments of C could be an argument pack if C is - // declared as template 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(IDC)) - CSE = cast(Fold->getLHS()); - else - CSE = cast(IDC); - ArrayRef OldConverted = CSE->getTemplateArguments(); - SmallVector NewConverted; - NewConverted.reserve(OldConverted.size()); - QualType ParamAsArgument(NewTTP->getTypeForDecl(), 0); - if (OldConverted.front().getKind() == TemplateArgument::Pack) { - // The case: - // template concept C = true; - // template 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(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(*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; - - /// 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>; - - /// 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>; - - ParentMapPointers PointerParents; - ParentMapOtherNodes OtherParents; - class ASTVisitor; - - static ast_type_traits::DynTypedNode - getSingleDynTypedNodeFromParentMap(ParentMapPointers::mapped_type U) { - if (const auto *D = U.dyn_cast()) - return ast_type_traits::DynTypedNode::create(*D); - if (const auto *S = U.dyn_cast()) - return ast_type_traits::DynTypedNode::create(*S); - return *U.get(); - } - - template - static ASTContext::DynTypedNodeList getDynNodeFromMap(const NodeTy &Node, - const MapTy &Map) { - auto I = Map.find(Node); - if (I == Map.end()) { - return llvm::ArrayRef(); - } - if (const auto *V = I->second.template dyn_cast()) { - return llvm::makeArrayRef(*V); - } - return getSingleDynTypedNodeFromParentMap(I->second); - } - -public: - ParentMap(ASTContext &Ctx); - ~ParentMap() { - for (const auto &Entry : PointerParents) { - if (Entry.second.is()) { - delete Entry.second.get(); - } else if (Entry.second.is()) { - delete Entry.second.get(); - } - } - for (const auto &Entry : OtherParents) { - if (Entry.second.is()) { - delete Entry.second.get(); - } else if (Entry.second.is()) { - delete Entry.second.get(); - } - } - } - - 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 &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 +ASTContext::getModulesWithMergedDefinition(const NamedDecl *Def) { + auto MergedIt = + MergedDefModules.find(cast(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()->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(T)->getElementType()); - break; - case Type::ConstantArray: { - const auto *CAT = cast(T); + // Model non-constant sized arrays as size zero, but track the alignment. + uint64_t Size = 0; + if (const auto *CAT = dyn_cast(T)) + Size = CAT->getSize().getZExtValue(); - TypeInfo EltInfo = getTypeInfo(CAT->getElementType()); - uint64_t Size = CAT->getSize().getZExtValue(); + TypeInfo EltInfo = getTypeInfo(cast(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(T); @@ -1967,6 +1938,17 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { break; } + case Type::ConstantMatrix: { + const auto *MT = cast(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(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(T)->getAdjustedType().getTypePtr()); case Type::ObjCInterface: { const auto *ObjCI = cast(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(T); + Align = + std::min(static_cast(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(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(D)) return false; @@ -4587,7 +4724,7 @@ TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) { } else if (auto *NTTP = dyn_cast(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 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(New->getTypeForDecl()); + SmallVector 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 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(T)) + return 0 + (EIT->getNumBits() << 3); + switch (cast(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(T); if (!BT) { if (isa(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(*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(), - getObjCObjectPointerType(From)->getAs()); + getObjCObjectPointerType(To)->castAs(), + getObjCObjectPointerType(From)->castAs()); } /// 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(); const auto *rbase = rhs->castAs(); const auto *lproto = dyn_cast(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())) return LHS; return {}; + case Type::ConstantMatrix: + if (areCompatMatrixTypes(LHSCan->castAs(), + RHSCan->castAs())) + 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()->isUnsigned(); + bool RHSUnsigned = RHS->castAs()->isUnsigned(); + unsigned LHSBits = LHS->castAs()->getNumBits(); + unsigned RHSBits = RHS->castAs()->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()) + 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(D)) return true; + else if (isa(D)) + return true; else if (isa(D)) return !D->getDeclContext()->isDependentContext(); else if (isa(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 -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 { -public: - ASTVisitor(ParentMap &Map, ASTContext &Context) - : Map(Map), Context(Context) {} - -private: - friend class RecursiveASTVisitor; - - using VisitorBase = RecursiveASTVisitor; - - bool shouldVisitTemplateInstantiations() const { return true; } - - bool shouldVisitImplicitCode() const { return true; } - - template - 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()) - NodeOrVector = D; - else if (const auto *S = ParentStack.back().get()) - NodeOrVector = S; - else - NodeOrVector = new ast_type_traits::DynTypedNode(ParentStack.back()); - } else { - if (!NodeOrVector.template is()) { - auto *Vector = new ParentVector( - 1, getSingleDynTypedNodeFromParentMap(NodeOrVector)); - delete NodeOrVector - .template dyn_cast(); - NodeOrVector = Vector; - } - - auto *Vector = NodeOrVector.template get(); - // 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(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 ParentStack; -}; - -ASTContext::ParentMap::ParentMap(ASTContext &Ctx) { - ASTVisitor(*this, Ctx).TraverseAST(Ctx); -} - -ASTContext::DynTypedNodeList -ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) { - std::unique_ptr &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(*this); - return P->getParents(Node); -} - bool ASTContext::ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, const ObjCMethodDecl *MethodImpl) { @@ -10958,3 +11151,16 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap &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 ea4d0dea58a3..05adf226bae3 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 22196a1a2600..284e5bdbc6b0 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(DC)->getASTContext(); - const SourceManager &SM = Ctx.getSourceManager(); - ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &Ctx.getSourceManager(), - SM.getDiagnostics().getShowColors(), Ctx.getPrintingPolicy()); + const ASTContext &Ctx = cast(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(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(this); +LLVM_DUMP_METHOD void Comment::dump(raw_ostream &OS, + const ASTContext &Context) const { + const auto *FC = dyn_cast(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(this); + const auto *FC = dyn_cast(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 22fb67478c96..3779e0cb872b 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -186,36 +186,25 @@ namespace clang { return import(*From); } - template - Expected> - importSeq(const T &From) { - Expected ToOrErr = import(From); - if (!ToOrErr) - return ToOrErr.takeError(); - return std::make_tuple(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 - Expected> - importSeq(const THead &FromHead, const TTail &...FromTail) { - Expected> ToHeadOrErr = importSeq(FromHead); - if (!ToHeadOrErr) - return ToHeadOrErr.takeError(); - Expected> 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 T importChecked(Error &Err, const T &From) { + // Don't attempt to import nodes if we hit an error earlier. + if (Err) + return T{}; + Expected MaybeVal = import(From); + if (!MaybeVal) { + Err = MaybeVal.takeError(); + return T{}; + } + return *MaybeVal; } -// Wrapper for an overload set. + // Wrapper for an overload set. template struct CallOverloadedCreateFun { - template - auto operator()(Args &&... args) - -> decltype(ToDeclT::Create(std::forward(args)...)) { + template decltype(auto) operator()(Args &&... args) { return ToDeclT::Create(std::forward(args)...); } }; @@ -474,7 +463,7 @@ namespace clang { ParmVarDecl *ToParam); template - 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 Error ImportArrayChecked(IIter Ibegin, IIter Iend, OIter Obegin) { - using ItemT = typename std::remove_reference::type; + using ItemT = std::remove_reference_t; for (; Ibegin != Iend; ++Ibegin, ++Obegin) { Expected ToOrErr = import(*Ibegin); if (!ToOrErr) @@ -984,7 +974,10 @@ Expected ASTNodeImporter::import(const LambdaCapture &From) { } template -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(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 ToTemplateArgs; + ArrayRef 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(*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(From); - Decl *ImportedDecl = (Decl*)*ImportedOrErr; + Decl *ImportedDecl = *ImportedOrErr; FieldDecl *FieldTo = dyn_cast_or_null(ImportedDecl); if (FieldFrom && FieldTo) { const RecordType *RecordFrom = FieldFrom->getType()->getAs(); @@ -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(From); + SmallVector 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(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(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( @@ -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 ConflictingDecls; auto FoundDecls = @@ -2605,10 +2613,15 @@ ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { } if (auto *FoundEnum = dyn_cast(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(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 Parameters; @@ -3302,10 +3311,10 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { if (auto *FromConstructor = dyn_cast(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( ToFunction, D, Importer.getToContext(), cast(DC), @@ -3320,16 +3329,12 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { return ToFunction; } else if (CXXDestructorDecl *FromDtor = dyn_cast(D)) { - auto Imp = - importSeq(const_cast(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(FromDtor->getOperatorDelete())); + auto ToThisArg = importChecked(Err, FromDtor->getOperatorDeleteThisArg()); + if (Err) + return std::move(Err); if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), cast(DC), @@ -3344,10 +3349,10 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { dyn_cast(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( ToFunction, D, Importer.getToContext(), cast(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 +static FriendCountAndPosition getFriendCountAndPosition( + const FriendDecl *FD, + llvm::function_ref GetCanTypeOrDecl) { + unsigned int FriendCount = 0; + llvm::Optional FriendPosition; + const auto *RD = cast(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(FD, [](const FriendDecl *F) { + if (TypeSourceInfo *TSI = F->getFriendType()) + return TSI->getType().getCanonicalType(); + llvm_unreachable("Wrong friend object type."); + }); + else + return getFriendCountAndPosition(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(DC); + // We try to maintain order and count of redundant friend declarations. + const auto *RD = cast(DC); FriendDecl *ImportedFriend = RD->getFirstFriend(); + SmallVector 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(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(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(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 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(Found)) { + if (VarTemplateDecl *FoundTemplate = dyn_cast(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(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(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 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 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 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 @@ -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 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 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(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 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 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 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 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 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 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 ToArgs(NumArgs); @@ -7733,44 +7663,32 @@ ExpectedStmt ASTNodeImporter::VisitLambdaExpr(LambdaExpr *E) { if (!ToCallOpOrErr) return ToCallOpOrErr.takeError(); - SmallVector 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 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 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 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 +ASTImporter::Import(ExprWithCleanups::CleanupObject From) { + if (auto *CLE = From.dyn_cast()) { + if (Expected R = Import(CLE)) + return ExprWithCleanups::CleanupObject(cast(*R)); + } + + // FIXME: Handle BlockDecl when we implement importing BlockExpr in + // ASTNodeImporter. + return make_error(ImportError::UnsupportedConstruct); +} + Expected ASTImporter::Import(QualType FromT) { if (FromT.isNull()) return QualType{}; @@ -8128,12 +8045,47 @@ Expected ASTImporter::Import(TypeSourceInfo *FromTSI) { } Expected 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(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 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(ErrOut); @@ -8274,7 +8226,7 @@ Expected ASTImporter::Import(Decl *FromD) { Imported(FromD, ToD); updateFlags(FromD, ToD); - SavedImportPaths[FromD].clear(); + SavedImportPaths.erase(FromD); return ToDOrErr; } @@ -8291,15 +8243,22 @@ Expected ASTImporter::ImportContext(DeclContext *FromDC) { // need it to have a definition. if (auto *ToRecord = dyn_cast(ToDC)) { auto *FromRecord = cast(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(ToDC)) { auto *FromEnum = cast(FromDC); if (ToEnum->isCompleteDefinition()) { @@ -8366,11 +8325,7 @@ Expected 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 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 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 7390329d4ed8..4d6fff8f3419 100644 --- a/clang/lib/AST/ASTImporterLookupTable.cpp +++ b/clang/lib/AST/ASTImporterLookupTable.cpp @@ -45,7 +45,11 @@ struct Builder : RecursiveASTVisitor { LT.add(RTy->getAsCXXRecordDecl()); else if (const auto *SpecTy = dyn_cast(Ty)) LT.add(SpecTy->getAsCXXRecordDecl()); - else if (isa(Ty)) { + else if (const auto *SubstTy = + dyn_cast(Ty)) { + if (SubstTy->getAsCXXRecordDecl()) + LT.add(SubstTy->getAsCXXRecordDecl()); + } else if (isa(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 db48405055cd..8b5b2444f1e2 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(T1); + const DependentSizedMatrixType *Mat2 = cast(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(T1); + const ConstantMatrixType *Mat2 = cast(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(T1); const auto *Proto2 = cast(T2); @@ -729,11 +751,31 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; break; - case Type::Auto: - if (!IsStructurallyEquivalent(Context, cast(T1)->getDeducedType(), - cast(T2)->getDeducedType())) + case Type::Auto: { + auto *Auto1 = cast(T1); + auto *Auto2 = cast(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 Auto1Args = + Auto1->getTypeConstraintArguments(); + ArrayRef 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(T1); @@ -935,6 +977,24 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, cast(T2)->getElementType())) return false; break; + case Type::ExtInt: { + const auto *Int1 = cast(T1); + const auto *Int2 = cast(T2); + + if (Int1->isUnsigned() != Int2->isUnsigned() || + Int1->getNumBits() != Int2->getNumBits()) + return false; + break; + } + case Type::DependentExtInt: { + const auto *Int1 = cast(T1); + const auto *Int2 = cast(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 a5570c329ae8..34fc587694be 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, "" }, @@ -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()) D->dump(OS); else if (const Stmt *S = get()) - S->dump(OS, SM); + S->dump(OS, Context); else if (const Type *T = get()) - 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 0ef925ec1c90..7818fbb1918b 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::isDeclareTargetDeclaration(const ValueDecl *VD) { + if (!VD->hasAttrs()) + return llvm::None; + if (const auto *Attr = VD->getAttr()) + return Attr->getMapType(); + + return llvm::None; +} + +llvm::Optional +OMPDeclareTargetDeclAttr::getDeviceType(const ValueDecl *VD) { + if (!VD->hasAttrs()) + return llvm::None; + if (const auto *Attr = VD->getAttr()) + 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 a3a3794b2edd..8af97119e3cf 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 Queue; const CXXRecordDecl *Record = this; - bool AllMatches = true; while (true) { for (const auto &I : Record->bases()) { const RecordType *Ty = I.getType()->getAs(); - if (!Ty) { - if (AllowShortCircuit) return false; - AllMatches = false; - continue; - } + if (!Ty) + return false; CXXRecordDecl *Base = cast_or_null(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 b306fcbb154f..bdc0dd47fb7d 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 namespace clang { namespace comments { diff --git a/clang/lib/AST/CommentSema.cpp b/clang/lib/AST/CommentSema.cpp index 53c1832d1dd2..7642e73fa171 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(D)) + return !record->isUnion(); + + return false; +} bool Sema::isClassOrStructDecl() { if (!ThisDeclInfo) return false; if (!ThisDeclInfo->IsFilled) inspectThisDecl(); - return ThisDeclInfo->CurrentDecl && - isa(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(ThisDeclInfo->CurrentDecl)) { + auto UnderlyingType = ThisTypedefDecl->getUnderlyingType(); + if (auto ThisElaboratedType = dyn_cast(UnderlyingType)) { + auto DesugaredType = ThisElaboratedType->desugar(); + if (auto *DesugaredTypePtr = DesugaredType.getTypePtrOrNull()) { + if (auto *ThisRecordType = dyn_cast(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 07673230357f..6b6826c02a12 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 000000000000..2333993dbeb4 --- /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(NoParens)) + D = DRE->getDecl(); + else if (const auto *ME = dyn_cast(NoParens)) + D = ME->getMemberDecl(); + if (!D) + return Deps; + for (const auto *I : D->specific_attrs()) { + 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(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(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(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(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(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 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(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(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(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 8e67c101dee1..d3f2c22e9cc3 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 0d30f64b992e..5c0a98815dd7 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(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( - 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(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(this)) + if (auto *MD = dyn_cast(this)) { if (auto *ID = MD->getClassInterface()) Ctx = ID; - if (auto *PD = dyn_cast(this)) { + } else if (auto *PD = dyn_cast(this)) { if (auto *MD = PD->getGetterMethodDecl()) if (auto *ID = MD->getClassInterface()) Ctx = ID; + } else if (auto *ID = dyn_cast(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 *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()) { - BuiltinID = AMAA->getBuiltinName()->getBuiltinID(); + if (const auto *ABAA = getAttr()) { + 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() && - !hasAttr()) + !hasAttr()) 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(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(); + 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 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(); 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() = EndLoc; } @@ -4959,7 +4993,7 @@ ImportDecl *ImportDecl::CreateDeserialized(ASTContext &C, unsigned ID, } ArrayRef ImportDecl::getIdentifierLocs() const { - if (!ImportedAndComplete.getInt()) + if (!isImportComplete()) return None; const auto *StoredLocs = getTrailingObjects(); @@ -4968,7 +5002,7 @@ ArrayRef ImportDecl::getIdentifierLocs() const { } SourceRange ImportDecl::getSourceRange() const { - if (!ImportedAndComplete.getInt()) + if (!isImportComplete()) return SourceRange(getLocation(), *getTrailingObjects()); return SourceRange(getLocation(), getIdentifierLocs().back()); diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 6ee767ccecf7..da1eadd9d931 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(this)) + return CTPSD->getTemplateParameters(); + if (auto *VTPSD = dyn_cast(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(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(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(this); + if (RD && RD->isDependentLambda()) + if (Decl *Context = RD->getLambdaContextDecl()) + return Context->getTemplateDepth(); + + const DeclContext *DC = + getFriendObjectKind() ? getLexicalDeclContext() : getDeclContext(); + return cast(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(LDC)) return false; + if (const auto *CRD = dyn_cast(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 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() || hasAttr(); + return hasAttr() || hasAttr() || + hasAttr(); } const Attr *Decl::getDefiningAttr() const { @@ -462,6 +508,8 @@ const Attr *Decl::getDefiningAttr() const { return AA; if (auto *IFA = getAttr()) return IFA; + if (auto *NZA = getAttr()) + 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(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 2ead1e70ea0d..6f1fd2f14ede 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 #include @@ -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 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()) + return true; + if (const auto *Dtor = Def->getDestructor()) + if (Dtor->hasAttr()) + 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 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(); if (!RT) continue; const auto *Base = cast(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()) + if (BestDynamicDecl->isEffectivelyFinal()) return DevirtualizedMethod; - if (const auto *dtor = BestDynamicDecl->getDestructor()) { - if (dtor->hasAttr()) - return DevirtualizedMethod; - } if (const auto *DRE = dyn_cast(Base)) { if (const auto *VD = dyn_cast(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(), + return CXXMethodDecl::getThisType(getType()->castAs(), getParent()); } QualType CXXMethodDecl::getThisObjectType() const { // Ditto getThisType. assert(isInstance() && "No 'this' for static methods!"); - - return CXXMethodDecl::getThisObjectType(getType()->getAs(), - getParent()); + return CXXMethodDecl::getThisObjectType( + getType()->castAs(), 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()->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()->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(DRE->getDecl()); + auto *VD = cast(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; + + 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 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(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 9a84e3c4a510..5c8b34731f36 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(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(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(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(Container); + ClassDecl = cast(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 4cedcbed0644..2e48b2b46c4d 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& 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(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(Param)) { + VisitTemplateTypeParmDecl(TTP); } else if (auto NTTP = dyn_cast(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(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 << "<>"; + 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 << "<>"; 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 95a2e26e0df8..7857e75f57a1 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 &AC) const { if (HasConstrainedParameters) - for (const NamedDecl *Param : *this) - if (const auto *TTP = dyn_cast(Param)) + for (const NamedDecl *Param : *this) { + if (const auto *TTP = dyn_cast(Param)) { if (const auto *TC = TTP->getTypeConstraint()) AC.push_back(TC->getImmediatelyDeclaredConstraint()); + } else if (const auto *NTTP = dyn_cast(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(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(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, + 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 ExpandedTypes, ArrayRef ExpandedTInfos) { + AutoType *AT = TInfo->getType()->getContainedAutoType(); return new (C, DC, - additionalSizeToAlloc>( - ExpandedTypes.size())) + additionalSizeToAlloc, + 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, + 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>( - NumExpandedTypes)) + new (C, ID, additionalSizeToAlloc, + 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 4eb11bc57e52..ecf676c9936d 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 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 73ddbc62482d..399e7e13c445 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(); } -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(E)); AssertResultStorageKind(StorageKind); + unsigned Size = totalSizeToAlloc( 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(); } ConstantExpr *ConstantExpr::CreateEmpty(const ASTContext &Context, - ResultStorageKind StorageKind, - EmptyShell Empty) { + ResultStorageKind StorageKind) { AssertResultStorageKind(StorageKind); + unsigned Size = totalSizeToAlloc( 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(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(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(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(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() = 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()->initializeFrom( TemplateKWLoc, *TemplateArgs, getTrailingObjects(), - 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()->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(HasFunctionName), - alignof(PredefinedExpr)); + void *Mem = Ctx.Allocate( + totalSizeToAlloc(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( + 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( + 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(HasFunctionName), - alignof(PredefinedExpr)); + void *Mem = Ctx.Allocate( + totalSizeToAlloc(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 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(ND)) - MC->mangleCXXCtor(CD, Ctor_Base, Out); + GD = GlobalDecl(CD, Ctor_Base); else if (const CXXDestructorDecl *DD = dyn_cast(ND)) - MC->mangleCXXDtor(DD, Dtor_Base, Out); + GD = GlobalDecl(DD, Dtor_Base); + else if (ND->hasAttr()) + GD = GlobalDecl(cast(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(DC)) Out << ComputeName(IK, DCDecl) << "_block_invoke"; - return Out.str(); + return std::string(Out.str()); } if (const FunctionDecl *FD = dyn_cast(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(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(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(), Str.data(), ByteLength); + + setDependence(ExprDependence::None); } StringLiteral::StringLiteral(EmptyShell Empty, unsigned NumConcatenated, @@ -1339,10 +1305,7 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef PreArgs, ArrayRef 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(Args.size(), MinNumArgs); unsigned NumPreArgs = PreArgs.size(); CallExprBits.NumPreArgs = NumPreArgs; @@ -1356,17 +1319,14 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef PreArgs, CallExprBits.UsesADL = static_cast(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(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(CEE)) { - CEE = NTTP->getReplacement()->IgnoreParenCasts(); + while (SubstNonTypeTemplateParmExpr *NTTP = + dyn_cast(CEE)) { + CEE = NTTP->getReplacement()->IgnoreParenImpCasts(); } // If we're calling a dereference, look at the pointer instead. - if (BinaryOperator *BO = dyn_cast(CEE)) { - if (BO->isPtrMemOp()) - CEE = BO->getRHS()->IgnoreParenCasts(); - } else if (UnaryOperator *UO = dyn_cast(CEE)) { - if (UO->getOpcode() == UO_Deref) - CEE = UO->getSubExpr()->IgnoreParenCasts(); + while (true) { + if (BinaryOperator *BO = dyn_cast(CEE)) { + if (BO->isPtrMemOp()) { + CEE = BO->getRHS()->IgnoreParenImpCasts(); + continue; + } + } else if (UnaryOperator *UO = dyn_cast(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(CEE)) return DRE->getDecl(); if (MemberExpr *ME = dyn_cast(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(getCallee()); - if (!ICE) // FIXME: deal with more complex calls (e.g. (func)(), (*func)()). - return 0; - - const DeclRefExpr *DRE = dyn_cast(ICE->getSubExpr()); - if (!DRE) - return 0; - - const FunctionDecl *FDecl = dyn_cast(DRE->getDecl()); - if (!FDecl) - return 0; - - if (!FDecl->getIdentifier()) - return 0; - - return FDecl->getBuiltinID(); + auto *FDecl = + dyn_cast_or_null(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 comps, ArrayRef exprs, + ArrayRef comps, ArrayRef 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(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(E)) - D = DRE->getDecl(); - else if (const auto *ME = dyn_cast(E)) - D = ME->getMemberDecl(); - - if (D) { - for (const auto *I : D->specific_attrs()) { - 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(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(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()->initializeFrom( TemplateKWLoc, *TemplateArgs, - E->getTrailingObjects(), Dependent, - InstantiationDependent, ContainsUnexpandedParameterPack); - if (InstantiationDependent) - E->setInstantiationDependent(true); + E->getTrailingObjects(), TemplateArgDeps); + if (TemplateArgDeps & TemplateArgumentDependence::Instantiation) + Deps |= ExprDependence::Instantiation; } else if (TemplateKWLoc.isValid()) { E->getTrailingObjects()->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 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 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(E)) + return true; + + // - subscripting (5.2.1), + if (isa(E)) + return true; + + // - class member access (5.2.5), + if (isa(E)) + return true; + + // - indirection (5.3.1), + if (auto *UO = dyn_cast(E)) + if (UO->getOpcode() == UO_Deref) + return true; + + if (auto *BO = dyn_cast(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(E)) + return CO->getTrueExpr()->isReadIfDiscardedInCPlusPlus11() && + CO->getFalseExpr()->isReadIfDiscardedInCPlusPlus11(); + // The related edge case of "*x ?: *x". + if (auto *BCO = + dyn_cast(E)) { + if (auto *OVE = dyn_cast(BCO->getTrueExpr())) + return OVE->getSourceExpr()->isReadIfDiscardedInCPlusPlus11() && + BCO->getFalseExpr()->isReadIfDiscardedInCPlusPlus11(); + } + + // Objective-C++ extensions to the rule. + if (isa(E) || isa(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(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(CE->getSubExpr()->IgnoreParens()); - if (!(DRE && isa(DRE->getDecl()) && - cast(DRE->getDecl())->hasLocalStorage()) && - !isa(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(SubE)) + if (auto *VD = dyn_cast(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(E)) + return PE->getSubExpr(); + return E; +} + static Expr *IgnoreParensSingleStep(Expr *E) { if (auto *PE = dyn_cast(E)) return PE->getSubExpr(); @@ -2919,9 +2879,6 @@ static Expr *IgnoreParensSingleStep(Expr *E) { return CE->getChosenSubExpr(); } - else if (auto *CE = dyn_cast(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(E)) { - if (C->getNumArgs() == 1) { + auto NumArgs = C->getNumArgs(); + if (NumArgs == 1 || + (NumArgs > 1 && isa(C->getArg(1)))) { Expr *A = C->getArg(0); if (A->getSourceRange() == SR || !isa(C)) E = A; @@ -3039,7 +3000,18 @@ Expr *Expr::IgnoreUnlessSpelledInSource() { } if (auto *C = dyn_cast(E)) { - Expr *ExprNode = C->getImplicitObjectArgument()->IgnoreParenImpCasts(); + Expr *ExprNode = C->getImplicitObjectArgument(); + if (ExprNode->getSourceRange() == SR) { + E = ExprNode; + continue; + } + if (auto *PE = dyn_cast(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(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(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(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(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 args, +ShuffleVectorExpr::ShuffleVectorExpr(const ASTContext &C, ArrayRef 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 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() + AssocExprStartIndex); std::copy(AssocTypes.begin(), AssocTypes.end(), getTrailingObjects()); + + 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() + AssocExprStartIndex); std::copy(AssocTypes.begin(), AssocTypes.end(), getTrailingObjects()); + + setDependence(computeDependence(this, ContainsUnexpandedParameterPack)); } GenericSelectionExpr::GenericSelectionExpr(EmptyShell Empty, unsigned NumAssocs) @@ -4287,15 +4279,11 @@ DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty, llvm::ArrayRef Designators, SourceLocation EqualOrColonLoc, bool GNUSyntax, - ArrayRef 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 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 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()[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(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(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(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 semantics, + Expr *syntax, ArrayRef 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(E)) assert(cast(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 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 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 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()); + setDependence(computeDependence(this)); +} + +RecoveryExpr *RecoveryExpr::Create(ASTContext &Ctx, QualType T, + SourceLocation BeginLoc, + SourceLocation EndLoc, + ArrayRef SubExprs) { + void *Mem = Ctx.Allocate(totalSizeToAlloc(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(NumSubExprs), + alignof(RecoveryExpr)); + return new (Mem) RecoveryExpr(EmptyShell(), NumSubExprs); +} + +void OMPArrayShapingExpr::setDimensions(ArrayRef Dims) { + assert( + NumDims == Dims.size() && + "Preallocated number of dimensions is different from the provided one."); + llvm::copy(Dims, getTrailingObjects()); +} + +void OMPArrayShapingExpr::setBracketsRanges(ArrayRef BR) { + assert( + NumDims == BR.size() && + "Preallocated number of dimensions is different from the provided one."); + llvm::copy(BR, getTrailingObjects()); +} + +OMPArrayShapingExpr::OMPArrayShapingExpr(QualType ExprTy, Expr *Op, + SourceLocation L, SourceLocation R, + ArrayRef 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 Dims, + ArrayRef BracketRanges) { + assert(Dims.size() == BracketRanges.size() && + "Different number of dimensions and brackets ranges."); + void *Mem = Context.Allocate( + totalSizeToAlloc(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(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()[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(RangeLocOffset::Total) + + static_cast(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()[I * static_cast(RangeExprOffset::Total) + + static_cast(RangeExprOffset::Begin)] = + Begin; + getTrailingObjects()[I * static_cast(RangeExprOffset::Total) + + static_cast(RangeExprOffset::End)] = End; + getTrailingObjects()[I * static_cast(RangeExprOffset::Total) + + static_cast(RangeExprOffset::Step)] = Step; + getTrailingObjects< + SourceLocation>()[I * static_cast(RangeLocOffset::Total) + + static_cast(RangeLocOffset::FirstColonLoc)] = + ColonLoc; + getTrailingObjects< + SourceLocation>()[I * static_cast(RangeLocOffset::Total) + + static_cast(RangeLocOffset::SecondColonLoc)] = + SecondColonLoc; +} + +Decl *OMPIteratorExpr::getIteratorDecl(unsigned I) { + return getTrailingObjects()[I]; +} + +OMPIteratorExpr::IteratorRange OMPIteratorExpr::getIteratorRange(unsigned I) { + IteratorRange Res; + Res.Begin = + getTrailingObjects()[I * static_cast( + RangeExprOffset::Total) + + static_cast(RangeExprOffset::Begin)]; + Res.End = + getTrailingObjects()[I * static_cast( + RangeExprOffset::Total) + + static_cast(RangeExprOffset::End)]; + Res.Step = + getTrailingObjects()[I * static_cast( + RangeExprOffset::Total) + + static_cast(RangeExprOffset::Step)]; + return Res; +} + +SourceLocation OMPIteratorExpr::getAssignLoc(unsigned I) const { + return getTrailingObjects< + SourceLocation>()[I * static_cast(RangeLocOffset::Total) + + static_cast(RangeLocOffset::AssignLoc)]; +} + +SourceLocation OMPIteratorExpr::getColonLoc(unsigned I) const { + return getTrailingObjects< + SourceLocation>()[I * static_cast(RangeLocOffset::Total) + + static_cast(RangeLocOffset::FirstColonLoc)]; +} + +SourceLocation OMPIteratorExpr::getSecondColonLoc(unsigned I) const { + return getTrailingObjects< + SourceLocation>()[I * static_cast(RangeLocOffset::Total) + + static_cast(RangeLocOffset::SecondColonLoc)]; +} + +void OMPIteratorExpr::setHelper(unsigned I, const OMPIteratorHelperData &D) { + getTrailingObjects()[I] = D; +} + +OMPIteratorHelperData &OMPIteratorExpr::getHelper(unsigned I) { + return getTrailingObjects()[I]; +} + +const OMPIteratorHelperData &OMPIteratorExpr::getHelper(unsigned I) const { + return getTrailingObjects()[I]; +} + +OMPIteratorExpr::OMPIteratorExpr( + QualType ExprTy, SourceLocation IteratorKwLoc, SourceLocation L, + SourceLocation R, ArrayRef Data, + ArrayRef 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 Data, + ArrayRef Helpers) { + assert(Data.size() == Helpers.size() && + "Data and helpers must have the same size."); + void *Mem = Context.Allocate( + totalSizeToAlloc( + Data.size(), Data.size() * static_cast(RangeExprOffset::Total), + Data.size() * static_cast(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( + NumIterators, NumIterators * static_cast(RangeExprOffset::Total), + NumIterators * static_cast(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 422227d787b1..5d99f61c579f 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()[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()[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()[placementNewArgsOffset() + I] = PlacementArgs[I]; - } - if (IsParenTypeId) getTrailingObjects()[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(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(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(*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()->initializeFrom( - TemplateKWLoc, *Args, getTrailingObjects(), - Dependent, InstantiationDependent, ContainsUnexpandedParameterPack); - ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; + TemplateKWLoc, *Args, getTrailingObjects(), Deps); } else if (TemplateKWLoc.isValid()) { getTrailingObjects()->initializeFrom( TemplateKWLoc); } + setDependence(computeDependence(this)); } DependentScopeDeclRefExpr *DependentScopeDeclRefExpr::Create( @@ -615,27 +525,27 @@ CXXOperatorCallExpr::CXXOperatorCallExpr(OverloadedOperatorKind OpKind, Expr *Fn, ArrayRef 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(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 Args, QualType Ty, ExprValueKind VK, - SourceLocation OperatorLoc, FPOptions FPFeatures, ADLCallKind UsesADL) { +CXXOperatorCallExpr * +CXXOperatorCallExpr::Create(const ASTContext &Ctx, + OverloadedOperatorKind OpKind, Expr *Fn, + ArrayRef 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 ""; } } @@ -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(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 Captures, bool ExplicitParams, + SourceLocation CaptureDefaultLoc, bool ExplicitParams, bool ExplicitResultType, ArrayRef 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 Captures, - bool ExplicitParams, bool ExplicitResultType, ArrayRef 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 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(Captures.size() + 1); + unsigned Size = totalSizeToAlloc(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(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(Body)) + return cast(CoroBody->getBody()); + return cast(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 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(&getStoredStmts()[NumCaptures]) = - getCallOperator()->getBody(); +bool LambdaExpr::isMutable() const { return !getCallOperator()->isConst(); } - return static_cast(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(); - 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()->initializeFrom( TemplateKWLoc, *TemplateArgs, getTrailingObjects(), - Dependent, InstantiationDependent, ContainsUnexpandedParameterPack); - if (ContainsUnexpandedParameterPack) - ExprBits.ContainsUnexpandedParameterPack = true; + Deps); } else if (TemplateKWLoc.isValid()) { getTrailingObjects()->initializeFrom( TemplateKWLoc); @@ -1430,6 +1348,7 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr( if (hasFirstQualifierFoundInScope()) *getTrailingObjects() = 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()); + 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 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(Kind) == TypeTraitExprBits.Kind && + "TypeTraitExprBits.Kind overflow!"); TypeTraitExprBits.Value = Value; TypeTraitExprBits.NumArgs = Args.size(); + assert(Args.size() == TypeTraitExprBits.NumArgs && + "TypeTraitExprBits.NumArgs overflow!"); auto **ToArgs = getTrailingObjects(); - - 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 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 Converted) { - assert(Converted.size() == NumTemplateArgs); - std::uninitialized_copy(Converted.begin(), Converted.end(), - getTrailingObjects()); - 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 ConvertedArgs, - const ConstraintSatisfaction *Satisfaction) { - void *Buffer = C.Allocate(totalSizeToAlloc( - 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( - NumTemplateArgs)); - return new (Buffer) ConceptSpecializationExpr(Empty, NumTemplateArgs); -} diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp index 9dbf6fe9e0f0..31aa734ffedb 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(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(E)->getPattern()); @@ -451,6 +458,7 @@ static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) { islvalue = isa(D) || isa(D) || isa(D) || isa(D) || + isa(D) || (Ctx.getLangOpts().CPlusPlus && (isa(D) || isa(D) || isa(D))); diff --git a/clang/lib/AST/ExprConcepts.cpp b/clang/lib/AST/ExprConcepts.cpp new file mode 100644 index 000000000000..d00d8329095c --- /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 +#include +#include + +using namespace clang; + +ConceptSpecializationExpr::ConceptSpecializationExpr( + const ASTContext &C, NestedNameSpecifierLoc NNS, + SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, + NamedDecl *FoundDecl, ConceptDecl *NamedConcept, + const ASTTemplateArgumentListInfo *ArgsAsWritten, + ArrayRef 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 Converted) { + assert(Converted.size() == NumTemplateArgs); + std::uninitialized_copy(Converted.begin(), Converted.end(), + getTrailingObjects()); +} + +ConceptSpecializationExpr * +ConceptSpecializationExpr::Create(const ASTContext &C, + NestedNameSpecifierLoc NNS, + SourceLocation TemplateKWLoc, + DeclarationNameInfo ConceptNameInfo, + NamedDecl *FoundDecl, + ConceptDecl *NamedConcept, + const ASTTemplateArgumentListInfo *ArgsAsWritten, + ArrayRef ConvertedArgs, + const ConstraintSatisfaction *Satisfaction) { + void *Buffer = C.Allocate(totalSizeToAlloc( + ConvertedArgs.size())); + return new (Buffer) ConceptSpecializationExpr(C, NNS, TemplateKWLoc, + ConceptNameInfo, FoundDecl, + NamedConcept, ArgsAsWritten, + ConvertedArgs, Satisfaction); +} + +ConceptSpecializationExpr::ConceptSpecializationExpr( + const ASTContext &C, ConceptDecl *NamedConcept, + ArrayRef 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 ConvertedArgs, + const ConstraintSatisfaction *Satisfaction, + bool Dependent, + bool ContainsUnexpandedParameterPack) { + void *Buffer = C.Allocate(totalSizeToAlloc( + 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( + NumTemplateArgs)); + return new (Buffer) ConceptSpecializationExpr(Empty, NumTemplateArgs); +} + +const TypeConstraint * +concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const { + assert(isTypeConstraint()); + auto TPL = + TypeConstraintInfo.getPointer().get(); + return cast(TPL->getParam(0)) + ->getTypeConstraint(); +} + +RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc, + RequiresExprBodyDecl *Body, + ArrayRef LocalParameters, + ArrayRef 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()); + std::copy(Requirements.begin(), Requirements.end(), + getTrailingObjects()); + 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 LocalParameters, + ArrayRef Requirements, + SourceLocation RBraceLoc) { + void *Mem = + C.Allocate(totalSizeToAlloc( + 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( + 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 c4b27b5d1daa..d20c2382b6ac 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 @@ -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(D)) return VD->hasGlobalStorage(); // ... the address of a function, - return isa(D); + // ... the address of a GUID [MS extension], + return isa(D) || isa(D); } if (B.is() || B.is()) @@ -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(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()) { + if (auto *FD = dyn_cast(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(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(); } @@ -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 +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(); + 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 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 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()) { + if (const ConstantExpr *CE = + dyn_cast_or_null(LVal.Base.dyn_cast())) { + /// 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()) { + // Allow reading from a GUID declaration. + if (auto *GD = dyn_cast(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(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(Declaration) && + if (!Info.Ctx.getLangOpts().CPlusPlus20 && isa(Declaration) && cast(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(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 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 ArgVector; } @@ -5447,6 +5743,8 @@ static bool EvaluateArgs(ArrayRef 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(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::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(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(this)->VisitCastExpr(E); } @@ -6900,12 +7214,10 @@ public: return Error(Callee); This = &ThisVal; } else if (const auto *PDE = dyn_cast(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(E->getDecl())) return Visit(BD->getBinding()); + if (const MSGuidDecl *GD = dyn_cast(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 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(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(Init); + } else if (Init) { + ResizedArrayCCE = cast(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()->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()->getNumElements() == + E->getType()->getAs()->getNumElements() && + RHS->getType()->getAs()->getNumElements() == + E->getType()->getAs()->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(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 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 &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(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 53d0e873f8c9..662bc325f12c 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 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 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(); ExpansionData *Expansions = HasPackExpansions ? getTrailingObjects() : 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 VK, Expansions[I].NumExpansionsPlusOne = 0; } } + setDependence(computeDependence(this)); } ObjCDictionaryLiteral * @@ -127,10 +111,7 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK, SelectorLocationsKind SelLocsK, ObjCMethodDecl *Method, ArrayRef 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(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 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(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 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(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 Args, @@ -182,18 +161,8 @@ void ObjCMessageExpr::initArgsAndSelLocs(ArrayRef 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 837be5527fce..257833182621 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 @@ -28,7 +30,7 @@ char ExternalASTSource::ID; ExternalASTSource::~ExternalASTSource() = default; -llvm::Optional +llvm::Optional 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 &Decls) {} diff --git a/clang/lib/AST/FormatString.cpp b/clang/lib/AST/FormatString.cpp index fcc0b3b11e25..83b952116a5e 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()) 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/Block.cpp b/clang/lib/AST/Interp/Block.cpp deleted file mode 100644 index 5fc93eb39f4e..000000000000 --- a/clang/lib/AST/Interp/Block.cpp +++ /dev/null @@ -1,87 +0,0 @@ -//===--- Block.cpp - 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. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Defines the classes describing allocated blocks. -// -//===----------------------------------------------------------------------===// - -#include "Block.h" -#include "Pointer.h" - -using namespace clang; -using namespace clang::interp; - - - -void Block::addPointer(Pointer *P) { - if (IsStatic) - return; - if (Pointers) - Pointers->Prev = P; - P->Next = Pointers; - P->Prev = nullptr; - Pointers = P; -} - -void Block::removePointer(Pointer *P) { - if (IsStatic) - return; - if (Pointers == P) - Pointers = P->Next; - if (P->Prev) - P->Prev->Next = P->Next; - if (P->Next) - P->Next->Prev = P->Prev; -} - -void Block::cleanup() { - if (Pointers == nullptr && IsDead) - (reinterpret_cast(this + 1) - 1)->free(); -} - -void Block::movePointer(Pointer *From, Pointer *To) { - if (IsStatic) - return; - To->Prev = From->Prev; - if (To->Prev) - To->Prev->Next = To; - To->Next = From->Next; - if (To->Next) - To->Next->Prev = To; - if (Pointers == From) - Pointers = To; - - From->Prev = nullptr; - From->Next = nullptr; -} - -DeadBlock::DeadBlock(DeadBlock *&Root, Block *Blk) - : Root(Root), B(Blk->Desc, Blk->IsStatic, Blk->IsExtern, /*isDead=*/true) { - // Add the block to the chain of dead blocks. - if (Root) - Root->Prev = this; - - Next = Root; - Prev = nullptr; - Root = this; - - // Transfer pointers. - B.Pointers = Blk->Pointers; - for (Pointer *P = Blk->Pointers; P; P = P->Next) - P->Pointee = &B; -} - -void DeadBlock::free() { - if (Prev) - Prev->Next = Next; - if (Next) - Next->Prev = Prev; - if (Root == this) - Root = Next; - ::free(this); -} diff --git a/clang/lib/AST/Interp/Block.h b/clang/lib/AST/Interp/Block.h deleted file mode 100644 index 97fb9a3ca096..000000000000 --- a/clang/lib/AST/Interp/Block.h +++ /dev/null @@ -1,140 +0,0 @@ -//===--- Block.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. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Defines the classes describing allocated blocks. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_INTERP_BLOCK_H -#define LLVM_CLANG_AST_INTERP_BLOCK_H - -#include "Descriptor.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" - -namespace clang { -namespace interp { -class Block; -class DeadBlock; -class Context; -class InterpState; -class Pointer; -class Function; -enum PrimType : unsigned; - -/// A memory block, either on the stack or in the heap. -/// -/// The storage described by the block immediately follows it in memory. -class Block { -public: - // Creates a new block. - Block(const llvm::Optional &DeclID, Descriptor *Desc, - bool IsStatic = false, bool IsExtern = false) - : DeclID(DeclID), IsStatic(IsStatic), IsExtern(IsExtern), Desc(Desc) {} - - Block(Descriptor *Desc, bool IsStatic = false, bool IsExtern = false) - : DeclID((unsigned)-1), IsStatic(IsStatic), IsExtern(IsExtern), - Desc(Desc) {} - - /// Returns the block's descriptor. - Descriptor *getDescriptor() const { return Desc; } - /// Checks if the block has any live pointers. - bool hasPointers() const { return Pointers; } - /// Checks if the block is extern. - bool isExtern() const { return IsExtern; } - /// Checks if the block has static storage duration. - bool isStatic() const { return IsStatic; } - /// Checks if the block is temporary. - bool isTemporary() const { return Desc->IsTemporary; } - /// Returns the size of the block. - InterpSize getSize() const { return Desc->getAllocSize(); } - /// Returns the declaration ID. - llvm::Optional getDeclID() const { return DeclID; } - - /// Returns a pointer to the stored data. - char *data() { return reinterpret_cast(this + 1); } - - /// Returns a view over the data. - template - T &deref() { return *reinterpret_cast(data()); } - - /// Invokes the constructor. - void invokeCtor() { - std::memset(data(), 0, getSize()); - if (Desc->CtorFn) - Desc->CtorFn(this, data(), Desc->IsConst, Desc->IsMutable, - /*isActive=*/true, Desc); - } - -protected: - friend class Pointer; - friend class DeadBlock; - friend class InterpState; - - Block(Descriptor *Desc, bool IsExtern, bool IsStatic, bool IsDead) - : IsStatic(IsStatic), IsExtern(IsExtern), IsDead(true), Desc(Desc) {} - - // Deletes a dead block at the end of its lifetime. - void cleanup(); - - // Pointer chain management. - void addPointer(Pointer *P); - void removePointer(Pointer *P); - void movePointer(Pointer *From, Pointer *To); - - /// Start of the chain of pointers. - Pointer *Pointers = nullptr; - /// Unique identifier of the declaration. - llvm::Optional DeclID; - /// Flag indicating if the block has static storage duration. - bool IsStatic = false; - /// Flag indicating if the block is an extern. - bool IsExtern = false; - /// Flag indicating if the pointer is dead. - bool IsDead = false; - /// Pointer to the stack slot descriptor. - Descriptor *Desc; -}; - -/// Descriptor for a dead block. -/// -/// Dead blocks are chained in a double-linked list to deallocate them -/// whenever pointers become dead. -class DeadBlock { -public: - /// Copies the block. - DeadBlock(DeadBlock *&Root, Block *Blk); - - /// Returns a pointer to the stored data. - char *data() { return B.data(); } - -private: - friend class Block; - friend class InterpState; - - void free(); - - /// Root pointer of the list. - DeadBlock *&Root; - /// Previous block in the list. - DeadBlock *Prev; - /// Next block in the list. - DeadBlock *Next; - - /// Actual block storing data and tracking pointers. - Block B; -}; - -} // namespace interp -} // namespace clang - -#endif diff --git a/clang/lib/AST/Interp/Boolean.h b/clang/lib/AST/Interp/Boolean.h index 3e6c8b5da9f0..2baa717311bc 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 - static typename std::enable_if::value, Boolean>::type - from(T Value) { + static std::enable_if_t::value, Boolean> from(T Value) { return Boolean(Value != 0); } template - static typename std::enable_if::type from( - Integral Value) { + static std::enable_if_t + from(Integral Value) { return Boolean(!Value.isZero()); } diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 1d0e34fc991f..716f28551e58 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 e7f9ba0f010a..3bfcdfcd4c58 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 e77a825eb1f2..293fdd4b3256 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 7cc788070de8..46cd611ee389 100644 --- a/clang/lib/AST/Interp/Integral.h +++ b/clang/lib/AST/Interp/Integral.h @@ -156,13 +156,12 @@ public: } template - static typename std::enable_if::value, Integral>::type - from(T Value) { + static std::enable_if_t::value, Integral> from(T Value) { return Integral(Value); } template - static typename std::enable_if::type + static std::enable_if_t from(Integral Value) { return Integral(Value.V); } @@ -206,52 +205,52 @@ public: private: template - static typename std::enable_if::value, bool>::type - CheckAddUB(T A, T B, T &R) { + static std::enable_if_t::value, bool> CheckAddUB(T A, T B, + T &R) { return llvm::AddOverflow(A, B, R); } template - static typename std::enable_if::value, bool>::type - CheckAddUB(T A, T B, T &R) { + static std::enable_if_t::value, bool> CheckAddUB(T A, T B, + T &R) { R = A + B; return false; } template - static typename std::enable_if::value, bool>::type - CheckSubUB(T A, T B, T &R) { + static std::enable_if_t::value, bool> CheckSubUB(T A, T B, + T &R) { return llvm::SubOverflow(A, B, R); } template - static typename std::enable_if::value, bool>::type - CheckSubUB(T A, T B, T &R) { + static std::enable_if_t::value, bool> CheckSubUB(T A, T B, + T &R) { R = A - B; return false; } template - static typename std::enable_if::value, bool>::type - CheckMulUB(T A, T B, T &R) { + static std::enable_if_t::value, bool> CheckMulUB(T A, T B, + T &R) { return llvm::MulOverflow(A, B, R); } template - static typename std::enable_if::value, bool>::type - CheckMulUB(T A, T B, T &R) { + static std::enable_if_t::value, bool> CheckMulUB(T A, T B, + T &R) { R = A * B; return false; } template - static typename std::enable_if::value, bool>::type + static std::enable_if_t::value, bool> CheckRange(int64_t V) { return Min <= V && V <= Max; } template - static typename std::enable_if::value, bool>::type + static std::enable_if_t::value, bool> CheckRange(int64_t V) { return V >= 0 && static_cast(V) <= Max; } diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp index 1a8109cedf76..cec3f6d6160e 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 c12caa639da7..a63c5a871ba3 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 ::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/InterpBlock.cpp b/clang/lib/AST/Interp/InterpBlock.cpp new file mode 100644 index 000000000000..ed6e8910194d --- /dev/null +++ b/clang/lib/AST/Interp/InterpBlock.cpp @@ -0,0 +1,87 @@ +//===--- Block.cpp - 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. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Defines the classes describing allocated blocks. +// +//===----------------------------------------------------------------------===// + +#include "InterpBlock.h" +#include "Pointer.h" + +using namespace clang; +using namespace clang::interp; + + + +void Block::addPointer(Pointer *P) { + if (IsStatic) + return; + if (Pointers) + Pointers->Prev = P; + P->Next = Pointers; + P->Prev = nullptr; + Pointers = P; +} + +void Block::removePointer(Pointer *P) { + if (IsStatic) + return; + if (Pointers == P) + Pointers = P->Next; + if (P->Prev) + P->Prev->Next = P->Next; + if (P->Next) + P->Next->Prev = P->Prev; +} + +void Block::cleanup() { + if (Pointers == nullptr && IsDead) + (reinterpret_cast(this + 1) - 1)->free(); +} + +void Block::movePointer(Pointer *From, Pointer *To) { + if (IsStatic) + return; + To->Prev = From->Prev; + if (To->Prev) + To->Prev->Next = To; + To->Next = From->Next; + if (To->Next) + To->Next->Prev = To; + if (Pointers == From) + Pointers = To; + + From->Prev = nullptr; + From->Next = nullptr; +} + +DeadBlock::DeadBlock(DeadBlock *&Root, Block *Blk) + : Root(Root), B(Blk->Desc, Blk->IsStatic, Blk->IsExtern, /*isDead=*/true) { + // Add the block to the chain of dead blocks. + if (Root) + Root->Prev = this; + + Next = Root; + Prev = nullptr; + Root = this; + + // Transfer pointers. + B.Pointers = Blk->Pointers; + for (Pointer *P = Blk->Pointers; P; P = P->Next) + P->Pointee = &B; +} + +void DeadBlock::free() { + if (Prev) + Prev->Next = Next; + if (Next) + Next->Prev = Prev; + if (Root == this) + Root = Next; + ::free(this); +} diff --git a/clang/lib/AST/Interp/InterpBlock.h b/clang/lib/AST/Interp/InterpBlock.h new file mode 100644 index 000000000000..0ccdef221c83 --- /dev/null +++ b/clang/lib/AST/Interp/InterpBlock.h @@ -0,0 +1,140 @@ +//===-- 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. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Defines the classes describing allocated blocks. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_INTERP_BLOCK_H +#define LLVM_CLANG_AST_INTERP_BLOCK_H + +#include "Descriptor.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" + +namespace clang { +namespace interp { +class Block; +class DeadBlock; +class Context; +class InterpState; +class Pointer; +class Function; +enum PrimType : unsigned; + +/// A memory block, either on the stack or in the heap. +/// +/// The storage described by the block immediately follows it in memory. +class Block { +public: + // Creates a new block. + Block(const llvm::Optional &DeclID, Descriptor *Desc, + bool IsStatic = false, bool IsExtern = false) + : DeclID(DeclID), IsStatic(IsStatic), IsExtern(IsExtern), Desc(Desc) {} + + Block(Descriptor *Desc, bool IsStatic = false, bool IsExtern = false) + : DeclID((unsigned)-1), IsStatic(IsStatic), IsExtern(IsExtern), + Desc(Desc) {} + + /// Returns the block's descriptor. + Descriptor *getDescriptor() const { return Desc; } + /// Checks if the block has any live pointers. + bool hasPointers() const { return Pointers; } + /// Checks if the block is extern. + bool isExtern() const { return IsExtern; } + /// Checks if the block has static storage duration. + bool isStatic() const { return IsStatic; } + /// Checks if the block is temporary. + bool isTemporary() const { return Desc->IsTemporary; } + /// Returns the size of the block. + InterpSize getSize() const { return Desc->getAllocSize(); } + /// Returns the declaration ID. + llvm::Optional getDeclID() const { return DeclID; } + + /// Returns a pointer to the stored data. + char *data() { return reinterpret_cast(this + 1); } + + /// Returns a view over the data. + template + T &deref() { return *reinterpret_cast(data()); } + + /// Invokes the constructor. + void invokeCtor() { + std::memset(data(), 0, getSize()); + if (Desc->CtorFn) + Desc->CtorFn(this, data(), Desc->IsConst, Desc->IsMutable, + /*isActive=*/true, Desc); + } + +protected: + friend class Pointer; + friend class DeadBlock; + friend class InterpState; + + Block(Descriptor *Desc, bool IsExtern, bool IsStatic, bool IsDead) + : IsStatic(IsStatic), IsExtern(IsExtern), IsDead(true), Desc(Desc) {} + + // Deletes a dead block at the end of its lifetime. + void cleanup(); + + // Pointer chain management. + void addPointer(Pointer *P); + void removePointer(Pointer *P); + void movePointer(Pointer *From, Pointer *To); + + /// Start of the chain of pointers. + Pointer *Pointers = nullptr; + /// Unique identifier of the declaration. + llvm::Optional DeclID; + /// Flag indicating if the block has static storage duration. + bool IsStatic = false; + /// Flag indicating if the block is an extern. + bool IsExtern = false; + /// Flag indicating if the pointer is dead. + bool IsDead = false; + /// Pointer to the stack slot descriptor. + Descriptor *Desc; +}; + +/// Descriptor for a dead block. +/// +/// Dead blocks are chained in a double-linked list to deallocate them +/// whenever pointers become dead. +class DeadBlock { +public: + /// Copies the block. + DeadBlock(DeadBlock *&Root, Block *Blk); + + /// Returns a pointer to the stored data. + char *data() { return B.data(); } + +private: + friend class Block; + friend class InterpState; + + void free(); + + /// Root pointer of the list. + DeadBlock *&Root; + /// Previous block in the list. + DeadBlock *Prev; + /// Next block in the list. + DeadBlock *Next; + + /// Actual block storing data and tracking pointers. + Block B; +}; + +} // namespace interp +} // namespace clang + +#endif diff --git a/clang/lib/AST/Interp/InterpFrame.h b/clang/lib/AST/Interp/InterpFrame.h index b8391b0bcf92..304e2ad66537 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 1a10723aaca5..ef2638e2a36b 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 b8fa98e24faa..f2f6e0e76018 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 e591c3399d7c..19c652b7331a 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 - static typename std::enable_if::value, T>::type + static std::enable_if_t::value, T> ReadHelper(const char *Ptr) { using namespace llvm::support; return endian::read(Ptr); } template - static typename std::enable_if::value, T>::type + static std::enable_if_t::value, T> ReadHelper(const char *Ptr) { using namespace llvm::support; auto Punned = endian::read(Ptr); diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 0d567edac521..ddfbe9f86499 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(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) { // ::= _Z // ::= // ::= Out << "_Z"; - if (const FunctionDecl *FD = dyn_cast(D)) - mangleFunctionEncoding(FD); - else if (const VarDecl *VD = dyn_cast(D)) + if (isa(GD.getDecl())) + mangleFunctionEncoding(GD); + else if (const VarDecl *VD = dyn_cast(GD.getDecl())) mangleName(VD); - else if (const IndirectFieldDecl *IFD = dyn_cast(D)) + else if (const IndirectFieldDecl *IFD = + dyn_cast(GD.getDecl())) mangleName(IFD->getAnonField()); + else if (const FieldDecl *FD = dyn_cast(GD.getDecl())) + mangleName(FD); + else if (const MSGuidDecl *GuidD = dyn_cast(GD.getDecl())) + mangleName(GuidD); else - mangleName(cast(D)); + llvm_unreachable("unexpected kind of global decl"); } -void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { +void CXXNameMangler::mangleFunctionEncoding(GlobalDecl GD) { + const FunctionDecl *FD = cast(GD.getDecl()); // ::= // 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(DC)); } -static const TemplateDecl * -isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) { +static const GlobalDecl +isTemplate(GlobalDecl GD, const TemplateArgumentList *&TemplateArgs) { + const NamedDecl *ND = cast(GD.getDecl()); // Check if we have a function template. if (const FunctionDecl *FD = dyn_cast(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(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(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(GD.getDecl()); if (const VarDecl *VD = dyn_cast(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(GD.getDecl()); // ::= [] // ::= [] // ::= [] @@ -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(GD.getDecl()); // ::= // ::= St # ::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(GD.getDecl()); // ::= // ::= 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(ND) || isa(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(GD.getDecl()); unsigned Arity = KnownArity; // ::= // ::= @@ -1278,6 +1292,16 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, break; } + if (auto *GD = dyn_cast(ND)) { + // We follow MSVC in mangling GUID declarations as if they were variables + // with a particular reserved name. Continue the pretense here. + SmallString 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()->getCallConv() == clang::CC_X86RegCall; - if (IsRegCall) + bool IsDeviceStub = + FD && FD->hasAttr() && + 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, // ::= * + // # Parameter types or 'v' for 'void'. if (const CXXRecordDecl *Record = dyn_cast(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) { + // ::= __device_stub__ + // ::= [n] + // ::= + Out << II->getLength() + sizeof("__device_stub__") - 1 << "__device_stub__" + << II->getName(); +} + void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) { // ::= // ::= [n] @@ -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(GD.getDecl()); // // ::= N [] [] E // ::= N [] [] @@ -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(DC)) + GD = GlobalDecl(CD, Ctor_Complete); + else if (auto *DD = dyn_cast(DC)) + GD = GlobalDecl(DD, Dtor_Complete); + else + GD = GlobalDecl(cast(DC)); + return GD; +} + +void CXXNameMangler::mangleLocalName(GlobalDecl GD, const AbiTagList *AdditionalAbiTags) { + const Decl *D = GD.getDecl(); // := Z E [] // := Z E s [] // := Z E d [ ] @@ -1564,7 +1619,7 @@ void CXXNameMangler::mangleLocalName(const Decl *D, else if (const BlockDecl *BD = dyn_cast(DC)) mangleBlockForPrefix(BD); else - mangleFunctionEncoding(cast(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(D); - mangleNestedName(ND, getEffectiveDeclContext(ND), AdditionalAbiTags, + mangleNestedName(GD, getEffectiveDeclContext(ND), AdditionalAbiTags, true /*NoFunction*/); } } else if (const BlockDecl *BD = dyn_cast(D)) { @@ -1628,7 +1683,7 @@ void CXXNameMangler::mangleLocalName(const Decl *D, assert(!AdditionalAbiTags && "Block cannot have additional abi tags"); mangleUnqualifiedBlock(BD); } else { - mangleUnqualifiedName(cast(D), AdditionalAbiTags); + mangleUnqualifiedName(GD, AdditionalAbiTags); } if (const NamedDecl *ND = dyn_cast(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 // in a given context; it is n-2 for the nth closure type // (in lexical order) with that same 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(); + auto *Proto = + Lambda->getLambdaTypeInfo()->getType()->castAs(); 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(GD.getDecl()); // ::=