diff options
author | dim <dim@FreeBSD.org> | 2017-04-02 17:24:58 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2017-04-02 17:24:58 +0000 |
commit | 60b571e49a90d38697b3aca23020d9da42fc7d7f (patch) | |
tree | 99351324c24d6cb146b6285b6caffa4d26fce188 /contrib/llvm/tools/clang/lib/AST | |
parent | bea1b22c7a9bce1dfdd73e6e5b65bc4752215180 (diff) | |
download | FreeBSD-src-60b571e49a90d38697b3aca23020d9da42fc7d7f.zip FreeBSD-src-60b571e49a90d38697b3aca23020d9da42fc7d7f.tar.gz |
Update clang, llvm, lld, lldb, compiler-rt and libc++ to 4.0.0 release:
MFC r309142 (by emaste):
Add WITH_LLD_AS_LD build knob
If set it installs LLD as /usr/bin/ld. LLD (as of version 3.9) is not
capable of linking the world and kernel, but can self-host and link many
substantial applications. GNU ld continues to be used for the world and
kernel build, regardless of how this knob is set.
It is on by default for arm64, and off for all other CPU architectures.
Sponsored by: The FreeBSD Foundation
MFC r310840:
Reapply 310775, now it also builds correctly if lldb is disabled:
Move llvm-objdump from CLANG_EXTRAS to installed by default
We currently install three tools from binutils 2.17.50: as, ld, and
objdump. Work is underway to migrate to a permissively-licensed
tool-chain, with one goal being the retirement of binutils 2.17.50.
LLVM's llvm-objdump is intended to be compatible with GNU objdump
although it is currently missing some options and may have formatting
differences. Enable it by default for testing and further investigation.
It may later be changed to install as /usr/bin/objdump, it becomes a
fully viable replacement.
Reviewed by: emaste
Differential Revision: https://reviews.freebsd.org/D8879
MFC r312855 (by emaste):
Rename LLD_AS_LD to LLD_IS_LD, for consistency with CLANG_IS_CC
Reported by: Dan McGregor <dan.mcgregor usask.ca>
MFC r313559 | glebius | 2017-02-10 18:34:48 +0100 (Fri, 10 Feb 2017) | 5 lines
Don't check struct rtentry on FreeBSD, it is an internal kernel structure.
On other systems it may be API structure for SIOCADDRT/SIOCDELRT.
Reviewed by: emaste, dim
MFC r314152 (by jkim):
Remove an assembler flag, which is redundant since r309124. The upstream
took care of it by introducing a macro NO_EXEC_STACK_DIRECTIVE.
http://llvm.org/viewvc/llvm-project?rev=273500&view=rev
Reviewed by: dim
MFC r314564:
Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to
4.0.0 (branches/release_40 296509). The release will follow soon.
Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11
support to build; see UPDATING for more information.
Also note that as of 4.0.0, lld should be able to link the base system
on amd64 and aarch64. See the WITH_LLD_IS_LLD setting in src.conf(5).
Though please be aware that this is work in progress.
Release notes for llvm, clang and lld will be available here:
<http://releases.llvm.org/4.0.0/docs/ReleaseNotes.html>
<http://releases.llvm.org/4.0.0/tools/clang/docs/ReleaseNotes.html>
<http://releases.llvm.org/4.0.0/tools/lld/docs/ReleaseNotes.html>
Thanks to Ed Maste, Jan Beich, Antoine Brodin and Eric Fiselier for
their help.
Relnotes: yes
Exp-run: antoine
PR: 215969, 216008
MFC r314708:
For now, revert r287232 from upstream llvm trunk (by Daniil Fukalov):
[SCEV] limit recursion depth of CompareSCEVComplexity
Summary:
CompareSCEVComplexity goes too deep (50+ on a quite a big unrolled
loop) and runs almost infinite time.
Added cache of "equal" SCEV pairs to earlier cutoff of further
estimation. Recursion depth limit was also introduced as a parameter.
Reviewers: sanjoy
Subscribers: mzolotukhin, tstellarAMD, llvm-commits
Differential Revision: https://reviews.llvm.org/D26389
This commit is the cause of excessive compile times on skein_block.c
(and possibly other files) during kernel builds on amd64.
We never saw the problematic behavior described in this upstream commit,
so for now it is better to revert it. An upstream bug has been filed
here: https://bugs.llvm.org/show_bug.cgi?id=32142
Reported by: mjg
MFC r314795:
Reapply r287232 from upstream llvm trunk (by Daniil Fukalov):
[SCEV] limit recursion depth of CompareSCEVComplexity
Summary:
CompareSCEVComplexity goes too deep (50+ on a quite a big unrolled
loop) and runs almost infinite time.
Added cache of "equal" SCEV pairs to earlier cutoff of further
estimation. Recursion depth limit was also introduced as a parameter.
Reviewers: sanjoy
Subscribers: mzolotukhin, tstellarAMD, llvm-commits
Differential Revision: https://reviews.llvm.org/D26389
Pull in r296992 from upstream llvm trunk (by Sanjoy Das):
[SCEV] Decrease the recursion threshold for CompareValueComplexity
Fixes PR32142.
r287232 accidentally increased the recursion threshold for
CompareValueComplexity from 2 to 32. This change reverses that
change by introducing a separate flag for CompareValueComplexity's
threshold.
The latter revision fixes the excessive compile times for skein_block.c.
MFC r314907 | mmel | 2017-03-08 12:40:27 +0100 (Wed, 08 Mar 2017) | 7 lines
Unbreak ARMv6 world.
The new compiler_rt library imported with clang 4.0.0 have several fatal
issues (non-functional __udivsi3 for example) with ARM specific instrict
functions. As temporary workaround, until upstream solve these problems,
disable all thumb[1][2] related feature.
MFC r315016:
Update clang, llvm, lld, lldb, compiler-rt and libc++ to 4.0.0 release.
We were already very close to the last release candidate, so this is a
pretty minor update.
Relnotes: yes
MFC r316005:
Revert r314907, and pull in r298713 from upstream compiler-rt trunk (by
Weiming Zhao):
builtins: Select correct code fragments when compiling for Thumb1/Thum2/ARM ISA.
Summary:
Value of __ARM_ARCH_ISA_THUMB isn't based on the actual compilation
mode (-mthumb, -marm), it reflect's capability of given CPU.
Due to this:
- use __tbumb__ and __thumb2__ insteand of __ARM_ARCH_ISA_THUMB
- use '.thumb' directive consistently in all affected files
- decorate all thumb functions using
DEFINE_COMPILERRT_THUMB_FUNCTION()
---------
Note: This patch doesn't fix broken Thumb1 variant of __udivsi3 !
Reviewers: weimingz, rengolin, compnerd
Subscribers: aemerson, dim
Differential Revision: https://reviews.llvm.org/D30938
Discussed with: mmel
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST')
47 files changed, 4502 insertions, 1397 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/APValue.cpp b/contrib/llvm/tools/clang/lib/AST/APValue.cpp index 3c58733..488ad33 100644 --- a/contrib/llvm/tools/clang/lib/AST/APValue.cpp +++ b/contrib/llvm/tools/clang/lib/AST/APValue.cpp @@ -17,8 +17,6 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" #include "clang/AST/Type.h" -#include "clang/Basic/Diagnostic.h" -#include "llvm/ADT/SmallString.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -29,6 +27,7 @@ namespace { CharUnits Offset; unsigned PathLength; unsigned CallIndex; + bool IsNullPtr; }; } @@ -151,10 +150,11 @@ APValue::APValue(const APValue &RHS) : Kind(Uninitialized) { MakeLValue(); if (RHS.hasLValuePath()) setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(), - RHS.isLValueOnePastTheEnd(), RHS.getLValueCallIndex()); + RHS.isLValueOnePastTheEnd(), RHS.getLValueCallIndex(), + RHS.isNullPointer()); else setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(), - RHS.getLValueCallIndex()); + RHS.getLValueCallIndex(), RHS.isNullPointer()); break; case Array: MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize()); @@ -263,7 +263,7 @@ LLVM_DUMP_METHOD void APValue::dump() const { static double GetApproxValue(const llvm::APFloat &F) { llvm::APFloat V = F; bool ignored; - V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven, + V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven, &ignored); return V.convertToDouble(); } @@ -581,8 +581,13 @@ unsigned APValue::getLValueCallIndex() const { return ((const LV*)(const char*)Data.buffer)->CallIndex; } +bool APValue::isNullPointer() const { + assert(isLValue() && "Invalid usage"); + return ((const LV*)(const char*)Data.buffer)->IsNullPtr; +} + void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath, - unsigned CallIndex) { + unsigned CallIndex, bool IsNullPtr) { assert(isLValue() && "Invalid accessor"); LV &LVal = *((LV*)(char*)Data.buffer); LVal.BaseAndIsOnePastTheEnd.setPointer(B); @@ -590,11 +595,12 @@ void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath, LVal.Offset = O; LVal.CallIndex = CallIndex; LVal.resizePath((unsigned)-1); + LVal.IsNullPtr = IsNullPtr; } void APValue::setLValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd, - unsigned CallIndex) { + unsigned CallIndex, bool IsNullPtr) { assert(isLValue() && "Invalid accessor"); LV &LVal = *((LV*)(char*)Data.buffer); LVal.BaseAndIsOnePastTheEnd.setPointer(B); @@ -603,6 +609,7 @@ void APValue::setLValue(LValueBase B, const CharUnits &O, LVal.CallIndex = CallIndex; LVal.resizePath(Path.size()); memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry)); + LVal.IsNullPtr = IsNullPtr; } const ValueDecl *APValue::getMemberPointerDecl() const { diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp index 6aad4d1..b531a66 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp @@ -34,7 +34,6 @@ #include "clang/Basic/Builtins.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/Capacity.h" @@ -652,6 +651,10 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( cast<TemplateTemplateParmDecl>(*P))); } + assert(!TTP->getRequiresClause() && + "Unexpected requires-clause on template template-parameter"); + Expr *const CanonRequiresClause = nullptr; + TemplateTemplateParmDecl *CanonTTP = TemplateTemplateParmDecl::Create(*this, getTranslationUnitDecl(), SourceLocation(), TTP->getDepth(), @@ -661,7 +664,8 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( TemplateParameterList::Create(*this, SourceLocation(), SourceLocation(), CanonParams, - SourceLocation())); + SourceLocation(), + CanonRequiresClause)); // Get the new insert position for the node we care about. Canonical = CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos); @@ -700,8 +704,8 @@ static const LangAS::Map *getAddressSpaceMap(const TargetInfo &T, // language-specific address space. static const unsigned FakeAddrSpaceMap[] = { 1, // opencl_global - 2, // opencl_local - 3, // opencl_constant + 3, // opencl_local + 2, // opencl_constant 4, // opencl_generic 5, // cuda_device 6, // cuda_constant @@ -788,7 +792,8 @@ ASTContext::~ASTContext() { MaterializedTemporaryValues) MTVPair.second->~APValue(); - llvm::DeleteContainerSeconds(MangleNumberingContexts); + for (const auto &Value : ModuleInitializers) + Value.second->~PerModuleInitializers(); } void ASTContext::ReleaseParentMapEntries() { @@ -902,6 +907,67 @@ void ASTContext::deduplicateMergedDefinitonsFor(NamedDecl *ND) { Merged.erase(std::remove(Merged.begin(), Merged.end(), nullptr), Merged.end()); } +void ASTContext::PerModuleInitializers::resolve(ASTContext &Ctx) { + if (LazyInitializers.empty()) + return; + + auto *Source = Ctx.getExternalSource(); + assert(Source && "lazy initializers but no external source"); + + auto LazyInits = std::move(LazyInitializers); + LazyInitializers.clear(); + + for (auto ID : LazyInits) + Initializers.push_back(Source->GetExternalDecl(ID)); + + assert(LazyInitializers.empty() && + "GetExternalDecl for lazy module initializer added more inits"); +} + +void ASTContext::addModuleInitializer(Module *M, Decl *D) { + // One special case: if we add a module initializer that imports another + // module, and that module's only initializer is an ImportDecl, simplify. + if (auto *ID = dyn_cast<ImportDecl>(D)) { + auto It = ModuleInitializers.find(ID->getImportedModule()); + + // Maybe the ImportDecl does nothing at all. (Common case.) + if (It == ModuleInitializers.end()) + return; + + // Maybe the ImportDecl only imports another ImportDecl. + auto &Imported = *It->second; + if (Imported.Initializers.size() + Imported.LazyInitializers.size() == 1) { + Imported.resolve(*this); + auto *OnlyDecl = Imported.Initializers.front(); + if (isa<ImportDecl>(OnlyDecl)) + D = OnlyDecl; + } + } + + auto *&Inits = ModuleInitializers[M]; + if (!Inits) + Inits = new (*this) PerModuleInitializers; + Inits->Initializers.push_back(D); +} + +void ASTContext::addLazyModuleInitializers(Module *M, ArrayRef<uint32_t> IDs) { + auto *&Inits = ModuleInitializers[M]; + if (!Inits) + Inits = new (*this) PerModuleInitializers; + Inits->LazyInitializers.insert(Inits->LazyInitializers.end(), + IDs.begin(), IDs.end()); +} + +ArrayRef<Decl*> ASTContext::getModuleInitializers(Module *M) { + auto It = ModuleInitializers.find(M); + if (It == ModuleInitializers.end()) + return None; + + auto *Inits = It->second; + Inits->resolve(*this); + return Inits->Initializers; +} + ExternCContextDecl *ASTContext::getExternCContextDecl() const { if (!ExternCContext) ExternCContext = ExternCContextDecl::Create(*this, getTranslationUnitDecl()); @@ -1204,9 +1270,8 @@ void ASTContext::setClassScopeSpecializationPattern(FunctionDecl *FD, } NamedDecl * -ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) { - llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos - = InstantiatedFromUsingDecl.find(UUD); +ASTContext::getInstantiatedFromUsingDecl(NamedDecl *UUD) { + auto Pos = InstantiatedFromUsingDecl.find(UUD); if (Pos == InstantiatedFromUsingDecl.end()) return nullptr; @@ -1214,11 +1279,15 @@ ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) { } void -ASTContext::setInstantiatedFromUsingDecl(UsingDecl *Inst, NamedDecl *Pattern) { +ASTContext::setInstantiatedFromUsingDecl(NamedDecl *Inst, NamedDecl *Pattern) { assert((isa<UsingDecl>(Pattern) || isa<UnresolvedUsingValueDecl>(Pattern) || isa<UnresolvedUsingTypenameDecl>(Pattern)) && "pattern decl is not a using decl"); + assert((isa<UsingDecl>(Inst) || + isa<UnresolvedUsingValueDecl>(Inst) || + isa<UnresolvedUsingTypenameDecl>(Inst)) && + "instantiation did not produce a using decl"); assert(!InstantiatedFromUsingDecl[Inst] && "pattern already exists"); InstantiatedFromUsingDecl[Inst] = Pattern; } @@ -1389,7 +1458,9 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const { T = getPointerType(RT->getPointeeType()); } QualType BaseT = getBaseElementType(T); - if (!BaseT->isIncompleteType() && !T->isFunctionType()) { + if (T->isFunctionType()) + Align = getTypeInfoImpl(T.getTypePtr()).Align; + else if (!BaseT->isIncompleteType()) { // Adjust alignments of declarations with array type by the // large-array alignment on the target. if (const ArrayType *arrayType = getAsArrayType(T)) { @@ -1504,6 +1575,30 @@ bool ASTContext::isAlignmentRequired(QualType T) const { return isAlignmentRequired(T.getTypePtr()); } +unsigned ASTContext::getTypeAlignIfKnown(QualType T) const { + // An alignment on a typedef overrides anything else. + if (auto *TT = T->getAs<TypedefType>()) + if (unsigned Align = TT->getDecl()->getMaxAlignment()) + return Align; + + // If we have an (array of) complete type, we're done. + T = getBaseElementType(T); + if (!T->isIncompleteType()) + return getTypeAlign(T); + + // If we had an array type, its element type might be a typedef + // type with an alignment attribute. + if (auto *TT = T->getAs<TypedefType>()) + if (unsigned Align = TT->getDecl()->getMaxAlignment()) + return Align; + + // Otherwise, see if the declaration of the type had an attribute. + if (auto *TT = T->getAs<TagType>()) + return TT->getDecl()->getMaxAlignment(); + + return 0; +} + TypeInfo ASTContext::getTypeInfo(const Type *T) const { TypeInfoMap::iterator I = MemoizedTypeInfo.find(T); if (I != MemoizedTypeInfo.end()) @@ -1671,24 +1766,29 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Width = Target->getPointerWidth(0); Align = Target->getPointerAlign(0); break; - case BuiltinType::OCLSampler: - // Samplers are modeled as integers. - Width = Target->getIntWidth(); - Align = Target->getIntAlign(); + case BuiltinType::OCLSampler: { + auto AS = getTargetAddressSpace(LangAS::opencl_constant); + Width = Target->getPointerWidth(AS); + Align = Target->getPointerAlign(AS); break; + } case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: case BuiltinType::OCLQueue: case BuiltinType::OCLNDRange: case BuiltinType::OCLReserveID: -#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ - case BuiltinType::Id: -#include "clang/Basic/OpenCLImageTypes.def" - // Currently these types are pointers to opaque types. Width = Target->getPointerWidth(0); Align = Target->getPointerAlign(0); break; +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLImageTypes.def" + { + auto AS = getTargetAddressSpace(Target->getOpenCLImageAddrSpace()); + Width = Target->getPointerWidth(AS); + Align = Target->getPointerAlign(AS); + } } break; case Type::ObjCObjectPointer: @@ -1787,6 +1887,9 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { case Type::Paren: return getTypeInfo(cast<ParenType>(T)->getInnerType().getTypePtr()); + case Type::ObjCTypeParam: + return getTypeInfo(cast<ObjCTypeParamType>(T)->desugar().getTypePtr()); + case Type::Typedef: { const TypedefNameDecl *Typedef = cast<TypedefType>(T)->getDecl(); TypeInfo Info = getTypeInfo(Typedef->getUnderlyingType().getTypePtr()); @@ -2284,6 +2387,14 @@ static QualType getFunctionTypeWithExceptionSpec( Proto->getExtProtoInfo().withExceptionSpec(ESI)); } +bool ASTContext::hasSameFunctionTypeIgnoringExceptionSpec(QualType T, + QualType U) { + return hasSameType(T, U) || + (getLangOpts().CPlusPlus1z && + hasSameType(getFunctionTypeWithExceptionSpec(*this, T, EST_None), + getFunctionTypeWithExceptionSpec(*this, U, EST_None))); +} + void ASTContext::adjustExceptionSpec( FunctionDecl *FD, const FunctionProtoType::ExceptionSpecInfo &ESI, bool AsWritten) { @@ -3039,46 +3150,160 @@ ASTContext::getCanonicalFunctionResultType(QualType ResultType) const { return CanResultType; } -QualType -ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, - const FunctionProtoType::ExtProtoInfo &EPI) const { +static bool isCanonicalExceptionSpecification( + const FunctionProtoType::ExceptionSpecInfo &ESI, bool NoexceptInType) { + if (ESI.Type == EST_None) + return true; + if (!NoexceptInType) + return false; + + // C++17 onwards: exception specification is part of the type, as a simple + // boolean "can this function type throw". + if (ESI.Type == EST_BasicNoexcept) + return true; + + // A dynamic exception specification is canonical if it only contains pack + // expansions (so we can't tell whether it's non-throwing) and all its + // contained types are canonical. + if (ESI.Type == EST_Dynamic) { + bool AnyPackExpansions = false; + for (QualType ET : ESI.Exceptions) { + if (!ET.isCanonical()) + return false; + if (ET->getAs<PackExpansionType>()) + AnyPackExpansions = true; + } + return AnyPackExpansions; + } + + // A noexcept(expr) specification is (possibly) canonical if expr is + // value-dependent. + if (ESI.Type == EST_ComputedNoexcept) + return ESI.NoexceptExpr && ESI.NoexceptExpr->isValueDependent(); + + return false; +} + +QualType ASTContext::getFunctionTypeInternal( + QualType ResultTy, ArrayRef<QualType> ArgArray, + const FunctionProtoType::ExtProtoInfo &EPI, bool OnlyWantCanonical) const { size_t NumArgs = ArgArray.size(); // Unique functions, to guarantee there is only one function of a particular // structure. llvm::FoldingSetNodeID ID; FunctionProtoType::Profile(ID, ResultTy, ArgArray.begin(), NumArgs, EPI, - *this); + *this, true); + + QualType Canonical; + bool Unique = false; void *InsertPos = nullptr; - if (FunctionProtoType *FTP = - FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos)) - return QualType(FTP, 0); + if (FunctionProtoType *FPT = + FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos)) { + QualType Existing = QualType(FPT, 0); + + // If we find a pre-existing equivalent FunctionProtoType, we can just reuse + // it so long as our exception specification doesn't contain a dependent + // noexcept expression, or we're just looking for a canonical type. + // Otherwise, we're going to need to create a type + // sugar node to hold the concrete expression. + if (OnlyWantCanonical || EPI.ExceptionSpec.Type != EST_ComputedNoexcept || + EPI.ExceptionSpec.NoexceptExpr == FPT->getNoexceptExpr()) + return Existing; + + // We need a new type sugar node for this one, to hold the new noexcept + // expression. We do no canonicalization here, but that's OK since we don't + // expect to see the same noexcept expression much more than once. + Canonical = getCanonicalType(Existing); + Unique = true; + } + + bool NoexceptInType = getLangOpts().CPlusPlus1z; + bool IsCanonicalExceptionSpec = + isCanonicalExceptionSpecification(EPI.ExceptionSpec, NoexceptInType); // Determine whether the type being created is already canonical or not. - bool isCanonical = - EPI.ExceptionSpec.Type == EST_None && isCanonicalResultType(ResultTy) && - !EPI.HasTrailingReturn; + bool isCanonical = !Unique && IsCanonicalExceptionSpec && + isCanonicalResultType(ResultTy) && !EPI.HasTrailingReturn; for (unsigned i = 0; i != NumArgs && isCanonical; ++i) if (!ArgArray[i].isCanonicalAsParam()) isCanonical = false; - // If this type isn't canonical, get the canonical version of it. - // The exception spec is not part of the canonical type. - QualType Canonical; - if (!isCanonical) { + if (OnlyWantCanonical) + assert(isCanonical && + "given non-canonical parameters constructing canonical type"); + + // If this type isn't canonical, get the canonical version of it if we don't + // already have it. The exception spec is only partially part of the + // canonical type, and only in C++17 onwards. + if (!isCanonical && Canonical.isNull()) { SmallVector<QualType, 16> CanonicalArgs; CanonicalArgs.reserve(NumArgs); for (unsigned i = 0; i != NumArgs; ++i) CanonicalArgs.push_back(getCanonicalParamType(ArgArray[i])); + llvm::SmallVector<QualType, 8> ExceptionTypeStorage; FunctionProtoType::ExtProtoInfo CanonicalEPI = EPI; CanonicalEPI.HasTrailingReturn = false; - CanonicalEPI.ExceptionSpec = FunctionProtoType::ExceptionSpecInfo(); + + if (IsCanonicalExceptionSpec) { + // Exception spec is already OK. + } else if (NoexceptInType) { + switch (EPI.ExceptionSpec.Type) { + case EST_Unparsed: case EST_Unevaluated: case EST_Uninstantiated: + // We don't know yet. It shouldn't matter what we pick here; no-one + // should ever look at this. + LLVM_FALLTHROUGH; + case EST_None: case EST_MSAny: + CanonicalEPI.ExceptionSpec.Type = EST_None; + break; + + // A dynamic exception specification is almost always "not noexcept", + // with the exception that a pack expansion might expand to no types. + case EST_Dynamic: { + bool AnyPacks = false; + for (QualType ET : EPI.ExceptionSpec.Exceptions) { + if (ET->getAs<PackExpansionType>()) + AnyPacks = true; + ExceptionTypeStorage.push_back(getCanonicalType(ET)); + } + if (!AnyPacks) + CanonicalEPI.ExceptionSpec.Type = EST_None; + else { + CanonicalEPI.ExceptionSpec.Type = EST_Dynamic; + CanonicalEPI.ExceptionSpec.Exceptions = ExceptionTypeStorage; + } + break; + } + + case EST_DynamicNone: case EST_BasicNoexcept: + CanonicalEPI.ExceptionSpec.Type = EST_BasicNoexcept; + break; + + case EST_ComputedNoexcept: + llvm::APSInt Value(1); + auto *E = CanonicalEPI.ExceptionSpec.NoexceptExpr; + if (!E || !E->isIntegerConstantExpr(Value, *this, nullptr, + /*IsEvaluated*/false)) { + // This noexcept specification is invalid. + // FIXME: Should this be able to happen? + CanonicalEPI.ExceptionSpec.Type = EST_None; + break; + } + + CanonicalEPI.ExceptionSpec.Type = + Value.getBoolValue() ? EST_BasicNoexcept : EST_None; + break; + } + } else { + CanonicalEPI.ExceptionSpec = FunctionProtoType::ExceptionSpecInfo(); + } // Adjust the canonical function result type. CanQualType CanResultTy = getCanonicalFunctionResultType(ResultTy); - Canonical = getFunctionType(CanResultTy, CanonicalArgs, CanonicalEPI); + Canonical = + getFunctionTypeInternal(CanResultTy, CanonicalArgs, CanonicalEPI, true); // Get the new insert position for the node we care about. FunctionProtoType *NewIP = @@ -3121,14 +3346,14 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, FunctionProtoType::ExtProtoInfo newEPI = EPI; new (FTP) FunctionProtoType(ResultTy, ArgArray, Canonical, newEPI); Types.push_back(FTP); - FunctionProtoTypes.InsertNode(FTP, InsertPos); + if (!Unique) + FunctionProtoTypes.InsertNode(FTP, InsertPos); return QualType(FTP, 0); } -/// Return pipe type for the specified type. -QualType ASTContext::getPipeType(QualType T) const { +QualType ASTContext::getPipeType(QualType T, bool ReadOnly) const { llvm::FoldingSetNodeID ID; - PipeType::Profile(ID, T); + PipeType::Profile(ID, T, ReadOnly); void *InsertPos = 0; if (PipeType *PT = PipeTypes.FindNodeOrInsertPos(ID, InsertPos)) @@ -3138,19 +3363,27 @@ QualType ASTContext::getPipeType(QualType T) const { // either, so fill in the canonical type field. QualType Canonical; if (!T.isCanonical()) { - Canonical = getPipeType(getCanonicalType(T)); + Canonical = getPipeType(getCanonicalType(T), ReadOnly); // Get the new insert position for the node we care about. PipeType *NewIP = PipeTypes.FindNodeOrInsertPos(ID, InsertPos); assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } - PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical); + PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical, ReadOnly); Types.push_back(New); PipeTypes.InsertNode(New, InsertPos); return QualType(New, 0); } +QualType ASTContext::getReadPipeType(QualType T) const { + return getPipeType(T, true); +} + +QualType ASTContext::getWritePipeType(QualType T) const { + return getPipeType(T, false); +} + #ifndef NDEBUG static bool NeedsInjectedClassNameType(const RecordDecl *D) { if (!isa<CXXRecordDecl>(D)) return false; @@ -3641,6 +3874,44 @@ ASTContext::getDependentTemplateSpecializationType( return QualType(T, 0); } +void +ASTContext::getInjectedTemplateArgs(const TemplateParameterList *Params, + SmallVectorImpl<TemplateArgument> &Args) { + Args.reserve(Args.size() + Params->size()); + + for (NamedDecl *Param : *Params) { + TemplateArgument Arg; + if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { + QualType ArgType = getTypeDeclType(TTP); + if (TTP->isParameterPack()) + ArgType = getPackExpansionType(ArgType, None); + + Arg = TemplateArgument(ArgType); + } else if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) { + Expr *E = new (*this) DeclRefExpr( + NTTP, /*enclosing*/false, + NTTP->getType().getNonLValueExprType(*this), + Expr::getValueKindForType(NTTP->getType()), NTTP->getLocation()); + + if (NTTP->isParameterPack()) + E = new (*this) PackExpansionExpr(DependentTy, E, NTTP->getLocation(), + None); + Arg = TemplateArgument(E); + } else { + auto *TTP = cast<TemplateTemplateParmDecl>(Param); + if (TTP->isParameterPack()) + Arg = TemplateArgument(TemplateName(TTP), Optional<unsigned>()); + else + Arg = TemplateArgument(TemplateName(TTP)); + } + + if (Param->isTemplateParameterPack()) + Arg = TemplateArgument::CreatePackCopy(*this, Arg); + + Args.push_back(Arg); + } +} + QualType ASTContext::getPackExpansionType(QualType Pattern, Optional<unsigned> NumExpansions) { llvm::FoldingSetNodeID ID; @@ -3798,6 +4069,116 @@ QualType ASTContext::getObjCObjectType( return QualType(T, 0); } +/// Apply Objective-C protocol qualifiers to the given type. +/// If this is for the canonical type of a type parameter, we can apply +/// protocol qualifiers on the ObjCObjectPointerType. +QualType +ASTContext::applyObjCProtocolQualifiers(QualType type, + ArrayRef<ObjCProtocolDecl *> protocols, bool &hasError, + bool allowOnPointerType) const { + hasError = false; + + if (const ObjCTypeParamType *objT = + dyn_cast<ObjCTypeParamType>(type.getTypePtr())) { + return getObjCTypeParamType(objT->getDecl(), protocols); + } + + // Apply protocol qualifiers to ObjCObjectPointerType. + if (allowOnPointerType) { + if (const ObjCObjectPointerType *objPtr = + dyn_cast<ObjCObjectPointerType>(type.getTypePtr())) { + const ObjCObjectType *objT = objPtr->getObjectType(); + // Merge protocol lists and construct ObjCObjectType. + SmallVector<ObjCProtocolDecl*, 8> protocolsVec; + protocolsVec.append(objT->qual_begin(), + objT->qual_end()); + protocolsVec.append(protocols.begin(), protocols.end()); + ArrayRef<ObjCProtocolDecl *> protocols = protocolsVec; + type = getObjCObjectType( + objT->getBaseType(), + objT->getTypeArgsAsWritten(), + protocols, + objT->isKindOfTypeAsWritten()); + return getObjCObjectPointerType(type); + } + } + + // Apply protocol qualifiers to ObjCObjectType. + if (const ObjCObjectType *objT = dyn_cast<ObjCObjectType>(type.getTypePtr())){ + // FIXME: Check for protocols to which the class type is already + // known to conform. + + return getObjCObjectType(objT->getBaseType(), + objT->getTypeArgsAsWritten(), + protocols, + objT->isKindOfTypeAsWritten()); + } + + // If the canonical type is ObjCObjectType, ... + if (type->isObjCObjectType()) { + // Silently overwrite any existing protocol qualifiers. + // TODO: determine whether that's the right thing to do. + + // FIXME: Check for protocols to which the class type is already + // known to conform. + return getObjCObjectType(type, { }, protocols, false); + } + + // id<protocol-list> + if (type->isObjCIdType()) { + const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>(); + type = getObjCObjectType(ObjCBuiltinIdTy, { }, protocols, + objPtr->isKindOfType()); + return getObjCObjectPointerType(type); + } + + // Class<protocol-list> + if (type->isObjCClassType()) { + const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>(); + type = getObjCObjectType(ObjCBuiltinClassTy, { }, protocols, + objPtr->isKindOfType()); + return getObjCObjectPointerType(type); + } + + hasError = true; + return type; +} + +QualType +ASTContext::getObjCTypeParamType(const ObjCTypeParamDecl *Decl, + ArrayRef<ObjCProtocolDecl *> protocols, + QualType Canonical) const { + // Look in the folding set for an existing type. + llvm::FoldingSetNodeID ID; + ObjCTypeParamType::Profile(ID, Decl, protocols); + void *InsertPos = nullptr; + if (ObjCTypeParamType *TypeParam = + ObjCTypeParamTypes.FindNodeOrInsertPos(ID, InsertPos)) + return QualType(TypeParam, 0); + + if (Canonical.isNull()) { + // We canonicalize to the underlying type. + Canonical = getCanonicalType(Decl->getUnderlyingType()); + if (!protocols.empty()) { + // Apply the protocol qualifers. + bool hasError; + Canonical = applyObjCProtocolQualifiers(Canonical, protocols, hasError, + true/*allowOnPointerType*/); + assert(!hasError && "Error when apply protocol qualifier to bound type"); + } + } + + unsigned size = sizeof(ObjCTypeParamType); + size += protocols.size() * sizeof(ObjCProtocolDecl *); + void *mem = Allocate(size, TypeAlignment); + ObjCTypeParamType *newType = new (mem) + ObjCTypeParamType(Decl, Canonical, protocols); + + Types.push_back(newType); + ObjCTypeParamTypes.InsertNode(newType, InsertPos); + return QualType(newType, 0); +} + /// ObjCObjectAdoptsQTypeProtocols - Checks that protocols in IC's /// protocol list adopt all protocols in QT's qualified-id protocol /// list. @@ -3983,7 +4364,7 @@ QualType ASTContext::getDecltypeType(Expr *e, QualType UnderlyingType) const { DependentDecltypeType *Canon = DependentDecltypeTypes.FindNodeOrInsertPos(ID, InsertPos); if (!Canon) { - // Build a new, canonical typeof(expr) type. + // Build a new, canonical decltype(expr) type. Canon = new (*this, TypeAlignment) DependentDecltypeType(*this, e); DependentDecltypeTypes.InsertNode(Canon, InsertPos); } @@ -4590,7 +4971,15 @@ QualType ASTContext::getArrayDecayedType(QualType Ty) const { QualType PtrTy = getPointerType(PrettyArrayType->getElementType()); // int x[restrict 4] -> int *restrict - return getQualifiedType(PtrTy, PrettyArrayType->getIndexTypeQualifiers()); + QualType Result = getQualifiedType(PtrTy, + PrettyArrayType->getIndexTypeQualifiers()); + + // int x[_Nullable] -> int * _Nullable + if (auto Nullability = Ty->getNullability(*this)) { + Result = const_cast<ASTContext *>(this)->getAttributedType( + AttributedType::getNullabilityAttrKind(*Nullability), Result, Result); + } + return Result; } QualType ASTContext::getBaseElementType(const ArrayType *array) const { @@ -5223,8 +5612,9 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const { return S; } -bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, - std::string& S) { +std::string +ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl) const { + std::string S; // Encode result type. getObjCEncodingForType(Decl->getReturnType(), S); CharUnits ParmOffset; @@ -5235,8 +5625,8 @@ bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, if (sz.isZero()) continue; - assert (sz.isPositive() && - "getObjCEncodingForFunctionDecl - Incomplete param type"); + assert(sz.isPositive() && + "getObjCEncodingForFunctionDecl - Incomplete param type"); ParmOffset += sz; } S += charUnitsToString(ParmOffset); @@ -5258,7 +5648,7 @@ bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, ParmOffset += getObjCEncodingTypeSize(PType); } - return false; + return S; } /// getObjCEncodingForMethodParameter - Return the encoded type for a single @@ -5280,11 +5670,11 @@ void ASTContext::getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT, /// getObjCEncodingForMethodDecl - Return the encoded type for this method /// declaration. -bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, - std::string& S, - bool Extended) const { +std::string ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, + bool Extended) const { // FIXME: This is not very efficient. // Encode return type. + std::string S; getObjCEncodingForMethodParameter(Decl->getObjCDeclQualifier(), Decl->getReturnType(), S, Extended); // Compute size of all parameters. @@ -5330,7 +5720,7 @@ bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, ParmOffset += getObjCEncodingTypeSize(PType); } - return false; + return S; } ObjCPropertyImplDecl * @@ -5378,9 +5768,9 @@ ASTContext::getObjCPropertyImplDeclForPropertyDecl( /// kPropertyNonAtomic = 'N' // property non-atomic /// }; /// @endcode -void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, - const Decl *Container, - std::string& S) const { +std::string +ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, + const Decl *Container) const { // Collect information from the property implementation decl(s). bool Dynamic = false; ObjCPropertyImplDecl *SynthesizePID = nullptr; @@ -5394,7 +5784,7 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, } // FIXME: This is not very efficient. - S = "T"; + std::string S = "T"; // Encode result type. // GCC has some special rules regarding encoding of properties which @@ -5443,6 +5833,7 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, } // FIXME: OBJCGC: weak & strong + return S; } /// getLegacyIntegralTypeEncoding - @@ -5833,18 +6224,20 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, ObjCInterfaceDecl *OI = T->castAs<ObjCObjectType>()->getInterface(); S += '{'; S += OI->getObjCRuntimeNameAsString(); - S += '='; - SmallVector<const ObjCIvarDecl*, 32> Ivars; - DeepCollectObjCIvars(OI, true, Ivars); - for (unsigned i = 0, e = Ivars.size(); i != e; ++i) { - const FieldDecl *Field = cast<FieldDecl>(Ivars[i]); - if (Field->isBitField()) - getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field); - else - getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD, - false, false, false, false, false, - EncodePointerToObjCTypedef, - NotEncodedT); + if (ExpandStructures) { + S += '='; + SmallVector<const ObjCIvarDecl*, 32> Ivars; + DeepCollectObjCIvars(OI, true, Ivars); + for (unsigned i = 0, e = Ivars.size(); i != e; ++i) { + const FieldDecl *Field = cast<FieldDecl>(Ivars[i]); + if (Field->isBitField()) + getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field); + else + getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD, + false, false, false, false, false, + EncodePointerToObjCTypedef, + NotEncodedT); + } } S += '}'; return; @@ -6369,9 +6762,8 @@ CreateX86_64ABIBuiltinVaListDecl(const ASTContext *Context) { static TypedefDecl *CreatePNaClABIBuiltinVaListDecl(const ASTContext *Context) { // typedef int __builtin_va_list[4]; llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 4); - QualType IntArrayType - = Context->getConstantArrayType(Context->IntTy, - Size, ArrayType::Normal, 0); + QualType IntArrayType = + Context->getConstantArrayType(Context->IntTy, Size, ArrayType::Normal, 0); return Context->buildImplicitTypedef(IntArrayType, "__builtin_va_list"); } @@ -6567,7 +6959,7 @@ ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS, QualifiedTemplateName *QTN = QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos); if (!QTN) { - QTN = new (*this, llvm::alignOf<QualifiedTemplateName>()) + QTN = new (*this, alignof(QualifiedTemplateName)) QualifiedTemplateName(NNS, TemplateKeyword, Template); QualifiedTemplateNames.InsertNode(QTN, InsertPos); } @@ -6595,11 +6987,11 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); if (CanonNNS == NNS) { - QTN = new (*this, llvm::alignOf<DependentTemplateName>()) + QTN = new (*this, alignof(DependentTemplateName)) DependentTemplateName(NNS, Name); } else { TemplateName Canon = getDependentTemplateName(CanonNNS, Name); - QTN = new (*this, llvm::alignOf<DependentTemplateName>()) + QTN = new (*this, alignof(DependentTemplateName)) DependentTemplateName(NNS, Name, Canon); DependentTemplateName *CheckQTN = DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos); @@ -6631,13 +7023,13 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); if (CanonNNS == NNS) { - QTN = new (*this, llvm::alignOf<DependentTemplateName>()) + QTN = new (*this, alignof(DependentTemplateName)) DependentTemplateName(NNS, Operator); } else { TemplateName Canon = getDependentTemplateName(CanonNNS, Operator); - QTN = new (*this, llvm::alignOf<DependentTemplateName>()) + QTN = new (*this, alignof(DependentTemplateName)) DependentTemplateName(NNS, Operator, Canon); - + DependentTemplateName *CheckQTN = DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos); assert(!CheckQTN && "Dependent template name canonicalization broken"); @@ -7388,7 +7780,7 @@ bool ASTContext::typesAreCompatible(QualType LHS, QualType RHS, bool CompareUnqualified) { if (getLangOpts().CPlusPlus) return hasSameType(LHS, RHS); - + return !mergeTypes(LHS, RHS, false, CompareUnqualified).isNull(); } @@ -7902,21 +8294,9 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, } case Type::Pipe: { - // Merge two pointer types, while trying to preserve typedef info - QualType LHSValue = LHS->getAs<PipeType>()->getElementType(); - QualType RHSValue = RHS->getAs<PipeType>()->getElementType(); - if (Unqualified) { - LHSValue = LHSValue.getUnqualifiedType(); - RHSValue = RHSValue.getUnqualifiedType(); - } - QualType ResultType = mergeTypes(LHSValue, RHSValue, false, - Unqualified); - if (ResultType.isNull()) return QualType(); - if (getCanonicalType(LHSValue) == getCanonicalType(ResultType)) - return LHS; - if (getCanonicalType(RHSValue) == getCanonicalType(ResultType)) - return RHS; - return getPipeType(ResultType); + assert(LHS != RHS && + "Equivalent pipe types should have already been handled!"); + return QualType(); } } @@ -8197,6 +8577,10 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'z'!"); Type = Context.getSizeType(); break; + case 'w': // wchar_t. + assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'w'!"); + Type = Context.getWideCharType(); + break; case 'F': Type = Context.getCFConstantStringType(); break; @@ -8385,13 +8769,16 @@ QualType ASTContext::GetBuiltinType(unsigned Id, bool Variadic = (TypeStr[0] == '.'); - // We really shouldn't be making a no-proto type here, especially in C++. - if (ArgTypes.empty() && Variadic) + // We really shouldn't be making a no-proto type here. + if (ArgTypes.empty() && Variadic && !getLangOpts().CPlusPlus) return getFunctionNoProtoType(ResType, EI); FunctionProtoType::ExtProtoInfo EPI; EPI.ExtInfo = EI; EPI.Variadic = Variadic; + if (getLangOpts().CPlusPlus && BuiltinInfo.isNoThrow(Id)) + EPI.ExceptionSpec.Type = + getLangOpts().CPlusPlus11 ? EST_BasicNoexcept : EST_DynamicNone; return getFunctionType(ResType, ArgTypes, EPI); } @@ -8576,6 +8963,8 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { return !D->getDeclContext()->isDependentContext(); else if (isa<OMPDeclareReductionDecl>(D)) return !D->getDeclContext()->isDependentContext(); + else if (isa<ImportDecl>(D)) + return true; else return false; @@ -8613,15 +9002,10 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { } } - GVALinkage Linkage = GetGVALinkageForFunction(FD); - // static, static inline, always_inline, and extern inline functions can // always be deferred. Normal inline functions can be deferred in C99/C++. // Implicit template instantiations can also be deferred in C++. - if (Linkage == GVA_Internal || Linkage == GVA_AvailableExternally || - Linkage == GVA_DiscardableODR) - return false; - return true; + return !isDiscardableGVALinkage(GetGVALinkageForFunction(FD)); } const VarDecl *VD = cast<VarDecl>(D); @@ -8632,9 +9016,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { return false; // Variables that can be needed in other TUs are required. - GVALinkage L = GetGVALinkageForVariable(VD); - if (L != GVA_Internal && L != GVA_AvailableExternally && - L != GVA_DiscardableODR) + if (!isDiscardableGVALinkage(GetGVALinkageForVariable(VD))) return true; // Variables that have destruction with side-effects are required. @@ -8643,9 +9025,18 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { // Variables that have initialization with side-effects are required. if (VD->getInit() && VD->getInit()->HasSideEffects(*this) && - !VD->evaluateValue()) + // We can get a value-dependent initializer during error recovery. + (VD->getInit()->isValueDependent() || !VD->evaluateValue())) return true; + // Likewise, variables with tuple-like bindings are required if their + // bindings have side-effects. + if (auto *DD = dyn_cast<DecompositionDecl>(VD)) + for (auto *BD : DD->bindings()) + if (auto *BindingVD = BD->getHoldingVar()) + if (DeclMustBeEmitted(BindingVD)) + return true; + return false; } @@ -8785,13 +9176,14 @@ unsigned ASTContext::getStaticLocalNumber(const VarDecl *VD) const { MangleNumberingContext & ASTContext::getManglingNumberContext(const DeclContext *DC) { assert(LangOpts.CPlusPlus); // We don't need mangling numbers for plain C. - MangleNumberingContext *&MCtx = MangleNumberingContexts[DC]; + std::unique_ptr<MangleNumberingContext> &MCtx = MangleNumberingContexts[DC]; if (!MCtx) MCtx = createMangleNumberingContext(); return *MCtx; } -MangleNumberingContext *ASTContext::createMangleNumberingContext() const { +std::unique_ptr<MangleNumberingContext> +ASTContext::createMangleNumberingContext() const { return ABI->createMangleNumberingContext(); } @@ -8808,18 +9200,6 @@ void ASTContext::addCopyConstructorForExceptionObject(CXXRecordDecl *RD, cast<CXXConstructorDecl>(CD->getFirstDecl())); } -void ASTContext::addDefaultArgExprForConstructor(const CXXConstructorDecl *CD, - unsigned ParmIdx, Expr *DAE) { - ABI->addDefaultArgExprForConstructor( - cast<CXXConstructorDecl>(CD->getFirstDecl()), ParmIdx, DAE); -} - -Expr *ASTContext::getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, - unsigned ParmIdx) { - return ABI->getDefaultArgExprForConstructor( - cast<CXXConstructorDecl>(CD->getFirstDecl()), ParmIdx); -} - void ASTContext::addTypedefNameForUnnamedTagDecl(TagDecl *TD, TypedefNameDecl *DD) { return ABI->addTypedefNameForUnnamedTagDecl(TD, DD); @@ -9098,6 +9478,16 @@ ASTContext::ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, } +uint64_t ASTContext::getTargetNullPointerValue(QualType QT) const { + unsigned AS; + if (QT->getUnqualifiedDesugaredType()->isNullPtrType()) + AS = 0; + else + AS = QT->getPointeeType().getAddressSpace(); + + return getTargetInfo().getNullPointerValue(AS); +} + // Explicitly instantiate this in case a Redeclarable<T> is used from a TU that // doesn't include ASTContext.h template diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp index 0f5a8b5..03e6115 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp @@ -20,7 +20,6 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" -#include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -937,6 +936,9 @@ class TemplateDiff { ++(*this); } + /// Return true if the iterator is non-singular. + bool isValid() const { return TST; } + /// isEnd - Returns true if the iterator is one past the end. bool isEnd() const { assert(TST && "InternalIterator is invalid with a null TST."); @@ -996,21 +998,21 @@ class TemplateDiff { } }; - bool UseDesugaredIterator; InternalIterator SugaredIterator; InternalIterator DesugaredIterator; public: TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST) - : UseDesugaredIterator(TST->isSugared() && !TST->isTypeAlias()), - SugaredIterator(TST), + : SugaredIterator(TST), DesugaredIterator( - GetTemplateSpecializationType(Context, TST->desugar())) {} + (TST->isSugared() && !TST->isTypeAlias()) + ? GetTemplateSpecializationType(Context, TST->desugar()) + : nullptr) {} /// &operator++ - Increment the iterator to the next template argument. TSTiterator &operator++() { ++SugaredIterator; - if (UseDesugaredIterator) + if (DesugaredIterator.isValid()) ++DesugaredIterator; return *this; } @@ -1033,12 +1035,12 @@ class TemplateDiff { /// hasDesugaredTA - Returns true if there is another TemplateArgument /// available. bool hasDesugaredTA() const { - return UseDesugaredIterator && !DesugaredIterator.isEnd(); + return DesugaredIterator.isValid() && !DesugaredIterator.isEnd(); } /// getDesugaredTA - Returns the desugared TemplateArgument. reference getDesugaredTA() const { - assert(UseDesugaredIterator && + assert(DesugaredIterator.isValid() && "Desugared TemplateArgument should not be used."); return *DesugaredIterator; } diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp index 872ba35..62261cc 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp @@ -428,6 +428,8 @@ namespace { void VisitFunctionDecl(const FunctionDecl *D); void VisitFieldDecl(const FieldDecl *D); void VisitVarDecl(const VarDecl *D); + void VisitDecompositionDecl(const DecompositionDecl *D); + void VisitBindingDecl(const BindingDecl *D); void VisitFileScopeAsmDecl(const FileScopeAsmDecl *D); void VisitImportDecl(const ImportDecl *D); void VisitPragmaCommentDecl(const PragmaCommentDecl *D); @@ -515,6 +517,8 @@ namespace { void VisitFloatingLiteral(const FloatingLiteral *Node); void VisitStringLiteral(const StringLiteral *Str); void VisitInitListExpr(const InitListExpr *ILE); + void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *ILE); + void VisitArrayInitIndexExpr(const ArrayInitIndexExpr *ILE); void VisitUnaryOperator(const UnaryOperator *Node); void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Node); void VisitMemberExpr(const MemberExpr *Node); @@ -543,6 +547,8 @@ namespace { dumpDecl(Node->getLambdaClass()); } void VisitSizeOfPackExpr(const SizeOfPackExpr *Node); + void + VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *Node); // ObjC void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node); @@ -1133,8 +1139,15 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { if (D->isPure()) OS << " pure"; - else if (D->isDeletedAsWritten()) + if (D->isDefaulted()) { + OS << " default"; + if (D->isDeleted()) + OS << "_delete"; + } + if (D->isDeletedAsWritten()) OS << " delete"; + if (D->isTrivial()) + OS << " trivial"; if (const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>()) { FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); @@ -1153,11 +1166,6 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { D->getTemplateSpecializationInfo()) dumpTemplateArgumentList(*FTSI->TemplateArguments); - for (ArrayRef<NamedDecl *>::iterator - I = D->getDeclsInPrototypeScope().begin(), - E = D->getDeclsInPrototypeScope().end(); I != E; ++I) - dumpDecl(*I); - if (!D->param_begin() && D->getNumParams()) dumpChild([=] { OS << "<<NULL params x " << D->getNumParams() << ">>"; }); else @@ -1217,6 +1225,19 @@ void ASTDumper::VisitVarDecl(const VarDecl *D) { } } +void ASTDumper::VisitDecompositionDecl(const DecompositionDecl *D) { + VisitVarDecl(D); + for (auto *B : D->bindings()) + dumpDecl(B); +} + +void ASTDumper::VisitBindingDecl(const BindingDecl *D) { + dumpName(D); + dumpType(D->getType()); + if (auto *E = D->getBinding()) + dumpStmt(E); +} + void ASTDumper::VisitFileScopeAsmDecl(const FileScopeAsmDecl *D) { dumpStmt(D->getAsmString()); } @@ -2005,6 +2026,14 @@ void ASTDumper::VisitInitListExpr(const InitListExpr *ILE) { } } +void ASTDumper::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) { + VisitExpr(E); +} + +void ASTDumper::VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E) { + VisitExpr(E); +} + void ASTDumper::VisitUnaryOperator(const UnaryOperator *Node) { VisitExpr(Node); OS << " " << (Node->isPostfix() ? "postfix" : "prefix") @@ -2179,6 +2208,11 @@ void ASTDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) { dumpTemplateArgument(A); } +void ASTDumper::VisitCXXDependentScopeMemberExpr( + const CXXDependentScopeMemberExpr *Node) { + VisitExpr(Node); + OS << " " << (Node->isArrow() ? "->" : ".") << Node->getMember(); +} //===----------------------------------------------------------------------===// // Obj-C Expressions @@ -2451,12 +2485,18 @@ void QualType::dump(const char *msg) const { dump(); } -LLVM_DUMP_METHOD void QualType::dump() const { - ASTDumper Dumper(llvm::errs(), nullptr, nullptr); +LLVM_DUMP_METHOD void QualType::dump() const { dump(llvm::errs()); } + +LLVM_DUMP_METHOD void QualType::dump(llvm::raw_ostream &OS) const { + ASTDumper Dumper(OS, nullptr, nullptr); Dumper.dumpTypeAsChild(*this); } -LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); } +LLVM_DUMP_METHOD void Type::dump() const { dump(llvm::errs()); } + +LLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS) const { + QualType(this, 0).dump(OS); +} //===----------------------------------------------------------------------===// // Decl method implementations diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp index bc1f9f9..1ccb746 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp @@ -39,7 +39,9 @@ namespace clang { // Importing types QualType VisitType(const Type *T); + QualType VisitAtomicType(const AtomicType *T); QualType VisitBuiltinType(const BuiltinType *T); + QualType VisitDecayedType(const DecayedType *T); QualType VisitComplexType(const ComplexType *T); QualType VisitPointerType(const PointerType *T); QualType VisitBlockPointerType(const BlockPointerType *T); @@ -88,6 +90,8 @@ namespace clang { DeclarationNameInfo& To); void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false); + bool ImportCastPath(CastExpr *E, CXXCastPath &Path); + typedef DesignatedInitExpr::Designator Designator; Designator ImportDesignator(const Designator &D); @@ -123,6 +127,8 @@ namespace clang { TemplateParameterList *ImportTemplateParameterList( TemplateParameterList *Params); TemplateArgument ImportTemplateArgument(const TemplateArgument &From); + TemplateArgumentLoc ImportTemplateArgumentLoc( + const TemplateArgumentLoc &TALoc, bool &Error); bool ImportTemplateArguments(const TemplateArgument *FromArgs, unsigned NumFromArgs, SmallVectorImpl<TemplateArgument> &ToArgs); @@ -136,6 +142,7 @@ namespace clang { bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To); Decl *VisitDecl(Decl *D); Decl *VisitAccessSpecDecl(AccessSpecDecl *D); + Decl *VisitStaticAssertDecl(StaticAssertDecl *D); Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D); Decl *VisitNamespaceDecl(NamespaceDecl *D); Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias); @@ -152,6 +159,7 @@ namespace clang { Decl *VisitCXXConversionDecl(CXXConversionDecl *D); Decl *VisitFieldDecl(FieldDecl *D); Decl *VisitIndirectFieldDecl(IndirectFieldDecl *D); + Decl *VisitFriendDecl(FriendDecl *D); Decl *VisitObjCIvarDecl(ObjCIvarDecl *D); Decl *VisitVarDecl(VarDecl *D); Decl *VisitImplicitParamDecl(ImplicitParamDecl *D); @@ -242,16 +250,32 @@ namespace clang { Expr *VisitConditionalOperator(ConditionalOperator *E); Expr *VisitBinaryConditionalOperator(BinaryConditionalOperator *E); Expr *VisitOpaqueValueExpr(OpaqueValueExpr *E); + Expr *VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E); + Expr *VisitExpressionTraitExpr(ExpressionTraitExpr *E); + Expr *VisitArraySubscriptExpr(ArraySubscriptExpr *E); Expr *VisitCompoundAssignOperator(CompoundAssignOperator *E); Expr *VisitImplicitCastExpr(ImplicitCastExpr *E); - Expr *VisitCStyleCastExpr(CStyleCastExpr *E); + Expr *VisitExplicitCastExpr(ExplicitCastExpr *E); + Expr *VisitOffsetOfExpr(OffsetOfExpr *OE); + Expr *VisitCXXThrowExpr(CXXThrowExpr *E); + Expr *VisitCXXNoexceptExpr(CXXNoexceptExpr *E); + Expr *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E); + Expr *VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E); + Expr *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E); + Expr *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE); + Expr *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E); + Expr *VisitCXXNewExpr(CXXNewExpr *CE); + Expr *VisitCXXDeleteExpr(CXXDeleteExpr *E); Expr *VisitCXXConstructExpr(CXXConstructExpr *E); Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E); + Expr *VisitExprWithCleanups(ExprWithCleanups *EWC); Expr *VisitCXXThisExpr(CXXThisExpr *E); Expr *VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E); Expr *VisitMemberExpr(MemberExpr *E); Expr *VisitCallExpr(CallExpr *E); Expr *VisitInitListExpr(InitListExpr *E); + Expr *VisitArrayInitLoopExpr(ArrayInitLoopExpr *E); + Expr *VisitArrayInitIndexExpr(ArrayInitIndexExpr *E); Expr *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E); Expr *VisitCXXNamedCastExpr(CXXNamedCastExpr *E); @@ -272,13 +296,26 @@ namespace clang { bool Failed = false; std::transform(Ibegin, Iend, Obegin, [&ImporterRef, &Failed](ItemT *From) -> ItemT * { - ItemT *To = ImporterRef.Import(From); + ItemT *To = cast_or_null<ItemT>( + ImporterRef.Import(From)); if (!To && From) Failed = true; return To; }); return Failed; } + + template<typename InContainerTy, typename OutContainerTy> + bool ImportContainerChecked(const InContainerTy &InContainer, + OutContainerTy &OutContainer) { + return ImportArrayChecked(InContainer.begin(), InContainer.end(), + OutContainer.begin()); + } + + template<typename InContainerTy, typename OIter> + bool ImportArrayChecked(const InContainerTy &InContainer, OIter Obegin) { + return ImportArrayChecked(InContainer.begin(), InContainer.end(), Obegin); + } }; } @@ -897,6 +934,23 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, break; } + case Type::ObjCTypeParam: { + const ObjCTypeParamType *Obj1 = cast<ObjCTypeParamType>(T1); + const ObjCTypeParamType *Obj2 = cast<ObjCTypeParamType>(T2); + if (!IsStructurallyEquivalent(Context, Obj1->getDecl(), + Obj2->getDecl())) + return false; + + if (Obj1->getNumProtocols() != Obj2->getNumProtocols()) + return false; + for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) { + if (!IsStructurallyEquivalent(Context, + Obj1->getProtocol(I), + Obj2->getProtocol(I))) + return false; + } + break; + } case Type::ObjCObject: { const ObjCObjectType *Obj1 = cast<ObjCObjectType>(T1); const ObjCObjectType *Obj2 = cast<ObjCObjectType>(T2); @@ -1549,6 +1603,14 @@ QualType ASTNodeImporter::VisitType(const Type *T) { return QualType(); } +QualType ASTNodeImporter::VisitAtomicType(const AtomicType *T){ + QualType UnderlyingType = Importer.Import(T->getValueType()); + if(UnderlyingType.isNull()) + return QualType(); + + return Importer.getToContext().getAtomicType(UnderlyingType); +} + QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { switch (T->getKind()) { #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ @@ -1594,6 +1656,14 @@ QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { llvm_unreachable("Invalid BuiltinType Kind!"); } +QualType ASTNodeImporter::VisitDecayedType(const DecayedType *T) { + QualType OrigT = Importer.Import(T->getOriginalType()); + if (OrigT.isNull()) + return QualType(); + + return Importer.getToContext().getDecayedType(OrigT); +} + QualType ASTNodeImporter::VisitComplexType(const ComplexType *T) { QualType ToElementType = Importer.Import(T->getElementType()); if (ToElementType.isNull()) @@ -2250,23 +2320,25 @@ bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To, TemplateParameterList *ASTNodeImporter::ImportTemplateParameterList( TemplateParameterList *Params) { - SmallVector<NamedDecl *, 4> ToParams; - ToParams.reserve(Params->size()); - for (TemplateParameterList::iterator P = Params->begin(), - PEnd = Params->end(); - P != PEnd; ++P) { - Decl *To = Importer.Import(*P); - if (!To) + SmallVector<NamedDecl *, 4> ToParams(Params->size()); + if (ImportContainerChecked(*Params, ToParams)) + return nullptr; + + Expr *ToRequiresClause; + if (Expr *const R = Params->getRequiresClause()) { + ToRequiresClause = Importer.Import(R); + if (!ToRequiresClause) return nullptr; - - ToParams.push_back(cast<NamedDecl>(To)); + } else { + ToRequiresClause = nullptr; } - + return TemplateParameterList::Create(Importer.getToContext(), Importer.Import(Params->getTemplateLoc()), Importer.Import(Params->getLAngleLoc()), ToParams, - Importer.Import(Params->getRAngleLoc())); + Importer.Import(Params->getRAngleLoc()), + ToRequiresClause); } TemplateArgument @@ -2340,6 +2412,31 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) { llvm_unreachable("Invalid template argument kind"); } +TemplateArgumentLoc ASTNodeImporter::ImportTemplateArgumentLoc( + const TemplateArgumentLoc &TALoc, bool &Error) { + Error = false; + TemplateArgument Arg = ImportTemplateArgument(TALoc.getArgument()); + TemplateArgumentLocInfo FromInfo = TALoc.getLocInfo(); + TemplateArgumentLocInfo ToInfo; + if (Arg.getKind() == TemplateArgument::Expression) { + Expr *E = Importer.Import(FromInfo.getAsExpr()); + ToInfo = TemplateArgumentLocInfo(E); + if (!E) + Error = true; + } else if (Arg.getKind() == TemplateArgument::Type) { + if (TypeSourceInfo *TSI = Importer.Import(FromInfo.getAsTypeSourceInfo())) + ToInfo = TemplateArgumentLocInfo(TSI); + else + Error = true; + } else { + ToInfo = TemplateArgumentLocInfo( + Importer.Import(FromInfo.getTemplateQualifierLoc()), + Importer.Import(FromInfo.getTemplateNameLoc()), + Importer.Import(FromInfo.getTemplateEllipsisLoc())); + } + return TemplateArgumentLoc(Arg, ToInfo); +} + bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs, unsigned NumFromArgs, SmallVectorImpl<TemplateArgument> &ToArgs) { @@ -2454,6 +2551,35 @@ Decl *ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) { return accessSpecDecl; } +Decl *ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) { + DeclContext *DC = Importer.ImportContext(D->getDeclContext()); + if (!DC) + return nullptr; + + DeclContext *LexicalDC = DC; + + // Import the location of this declaration. + SourceLocation Loc = Importer.Import(D->getLocation()); + + Expr *AssertExpr = Importer.Import(D->getAssertExpr()); + if (!AssertExpr) + return nullptr; + + StringLiteral *FromMsg = D->getMessage(); + StringLiteral *ToMsg = cast_or_null<StringLiteral>(Importer.Import(FromMsg)); + if (!ToMsg && FromMsg) + return nullptr; + + StaticAssertDecl *ToD = StaticAssertDecl::Create( + Importer.getToContext(), DC, Loc, AssertExpr, ToMsg, + Importer.Import(D->getRParenLoc()), D->isFailed()); + + ToD->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToD); + Importer.Imported(D, ToD); + return ToD; +} + Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { // Import the major distinguishing characteristics of this namespace. DeclContext *DC, *LexicalDC; @@ -3303,6 +3429,70 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { return ToIndirectField; } +Decl *ASTNodeImporter::VisitFriendDecl(FriendDecl *D) { + // Import the major distinguishing characteristics of a declaration. + DeclContext *DC = Importer.ImportContext(D->getDeclContext()); + DeclContext *LexicalDC = D->getDeclContext() == D->getLexicalDeclContext() + ? DC : Importer.ImportContext(D->getLexicalDeclContext()); + if (!DC || !LexicalDC) + return nullptr; + + // Determine whether we've already imported this decl. + // FriendDecl is not a NamedDecl so we cannot use localUncachedLookup. + auto *RD = cast<CXXRecordDecl>(DC); + FriendDecl *ImportedFriend = RD->getFirstFriend(); + StructuralEquivalenceContext Context( + Importer.getFromContext(), Importer.getToContext(), + Importer.getNonEquivalentDecls(), false, false); + + while (ImportedFriend) { + if (D->getFriendDecl() && ImportedFriend->getFriendDecl()) { + if (Context.IsStructurallyEquivalent(D->getFriendDecl(), + ImportedFriend->getFriendDecl())) + return Importer.Imported(D, ImportedFriend); + + } else if (D->getFriendType() && ImportedFriend->getFriendType()) { + if (Importer.IsStructurallyEquivalent( + D->getFriendType()->getType(), + ImportedFriend->getFriendType()->getType(), true)) + return Importer.Imported(D, ImportedFriend); + } + ImportedFriend = ImportedFriend->getNextFriend(); + } + + // Not found. Create it. + FriendDecl::FriendUnion ToFU; + if (NamedDecl *FriendD = D->getFriendDecl()) + ToFU = cast_or_null<NamedDecl>(Importer.Import(FriendD)); + else + ToFU = Importer.Import(D->getFriendType()); + if (!ToFU) + return nullptr; + + SmallVector<TemplateParameterList *, 1> ToTPLists(D->NumTPLists); + TemplateParameterList **FromTPLists = + D->getTrailingObjects<TemplateParameterList *>(); + for (unsigned I = 0; I < D->NumTPLists; I++) { + TemplateParameterList *List = ImportTemplateParameterList(FromTPLists[I]); + if (!List) + return nullptr; + ToTPLists[I] = List; + } + + FriendDecl *FrD = FriendDecl::Create(Importer.getToContext(), DC, + Importer.Import(D->getLocation()), + ToFU, Importer.Import(D->getFriendLoc()), + ToTPLists); + + Importer.Imported(D, FrD); + RD->pushFriendDecl(FrD); + + FrD->setAccess(D->getAccess()); + FrD->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(FrD); + return FrD; +} + Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { // Import the major distinguishing characteristics of an ivar. DeclContext *DC, *LexicalDC; @@ -4481,8 +4671,7 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { ClassTemplateDecl *D2 = ClassTemplateDecl::Create(Importer.getToContext(), DC, Loc, Name, TemplateParams, - D2Templated, - /*PrevDecl=*/nullptr); + D2Templated); D2Templated->setDescribedClassTemplate(D2); D2->setAccess(D->getAccess()); @@ -4859,11 +5048,10 @@ Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { } SmallVector<Expr *, 4> Exprs(S->getNumOutputs() + S->getNumInputs()); - if (ImportArrayChecked(S->begin_outputs(), S->end_outputs(), Exprs.begin())) + if (ImportContainerChecked(S->outputs(), Exprs)) return nullptr; - if (ImportArrayChecked(S->begin_inputs(), S->end_inputs(), - Exprs.begin() + S->getNumOutputs())) + if (ImportArrayChecked(S->inputs(), Exprs.begin() + S->getNumOutputs())) return nullptr; StringLiteral *AsmStr = cast_or_null<StringLiteral>( @@ -4906,8 +5094,8 @@ Stmt *ASTNodeImporter::VisitNullStmt(NullStmt *S) { Stmt *ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) { llvm::SmallVector<Stmt *, 8> ToStmts(S->size()); - - if (ImportArrayChecked(S->body_begin(), S->body_end(), ToStmts.begin())) + + if (ImportContainerChecked(S->body(), ToStmts)) return nullptr; SourceLocation ToLBraceLoc = Importer.Import(S->getLBracLoc()); @@ -5361,7 +5549,7 @@ Expr *ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) { return nullptr; return new (Importer.getToContext()) GNUNullExpr( - T, Importer.Import(E->getExprLoc())); + T, Importer.Import(E->getLocStart())); } Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) { @@ -5375,7 +5563,7 @@ Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) { return nullptr; return new (Importer.getToContext()) PredefinedExpr( - Importer.Import(E->getExprLoc()), T, E->getIdentType(), SL); + Importer.Import(E->getLocStart()), T, E->getIdentType(), SL); } Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { @@ -5394,6 +5582,20 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { if (T.isNull()) return nullptr; + + TemplateArgumentListInfo ToTAInfo; + TemplateArgumentListInfo *ResInfo = nullptr; + if (E->hasExplicitTemplateArgs()) { + for (const auto &FromLoc : E->template_arguments()) { + bool Error = false; + TemplateArgumentLoc ToTALoc = ImportTemplateArgumentLoc(FromLoc, Error); + if (Error) + return nullptr; + ToTAInfo.addArgument(ToTALoc); + } + ResInfo = &ToTAInfo; + } + DeclRefExpr *DRE = DeclRefExpr::Create(Importer.getToContext(), Importer.Import(E->getQualifierLoc()), Importer.Import(E->getTemplateKeywordLoc()), @@ -5401,8 +5603,7 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { E->refersToEnclosingVariableOrCapture(), Importer.Import(E->getLocation()), T, E->getValueKind(), - FoundD, - /*FIXME:TemplateArgs=*/nullptr); + FoundD, ResInfo); if (E->hadMultipleCandidates()) DRE->setHadMultipleCandidates(true); return DRE; @@ -5411,7 +5612,7 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { Expr *ASTNodeImporter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) - return NULL; + return nullptr; return new (Importer.getToContext()) ImplicitValueInitExpr(T); } @@ -5580,8 +5781,7 @@ Expr *ASTNodeImporter::VisitParenExpr(ParenExpr *E) { Expr *ASTNodeImporter::VisitParenListExpr(ParenListExpr *E) { SmallVector<Expr *, 4> Exprs(E->getNumExprs()); - if (ImportArrayChecked( - E->getExprs(), E->getExprs() + E->getNumExprs(), Exprs.begin())) + if (ImportContainerChecked(E->exprs(), Exprs)) return nullptr; return new (Importer.getToContext()) ParenListExpr( @@ -5719,6 +5919,38 @@ Expr *ASTNodeImporter::VisitBinaryConditionalOperator( T, E->getValueKind(), E->getObjectKind()); } +Expr *ASTNodeImporter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + TypeSourceInfo *ToQueried = Importer.Import(E->getQueriedTypeSourceInfo()); + if (!ToQueried) + return nullptr; + + Expr *Dim = Importer.Import(E->getDimensionExpression()); + if (!Dim && E->getDimensionExpression()) + return nullptr; + + return new (Importer.getToContext()) ArrayTypeTraitExpr( + Importer.Import(E->getLocStart()), E->getTrait(), ToQueried, + E->getValue(), Dim, Importer.Import(E->getLocEnd()), T); +} + +Expr *ASTNodeImporter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *ToQueried = Importer.Import(E->getQueriedExpression()); + if (!ToQueried) + return nullptr; + + return new (Importer.getToContext()) ExpressionTraitExpr( + Importer.Import(E->getLocStart()), E->getTrait(), ToQueried, + E->getValue(), Importer.Import(E->getLocEnd()), T); +} + Expr *ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) @@ -5729,10 +5961,28 @@ Expr *ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { return nullptr; return new (Importer.getToContext()) OpaqueValueExpr( - Importer.Import(E->getExprLoc()), T, E->getValueKind(), + Importer.Import(E->getLocation()), T, E->getValueKind(), E->getObjectKind(), SourceExpr); } +Expr *ASTNodeImporter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *ToLHS = Importer.Import(E->getLHS()); + if (!ToLHS) + return nullptr; + + Expr *ToRHS = Importer.Import(E->getRHS()); + if (!ToRHS) + return nullptr; + + return new (Importer.getToContext()) ArraySubscriptExpr( + ToLHS, ToRHS, T, E->getValueKind(), E->getObjectKind(), + Importer.Import(E->getRBracketLoc())); +} + Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) @@ -5763,11 +6013,14 @@ Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { E->isFPContractable()); } -static bool ImportCastPath(CastExpr *E, CXXCastPath &Path) { - if (E->path_empty()) return false; - - // TODO: import cast paths - return true; +bool ASTNodeImporter::ImportCastPath(CastExpr *CE, CXXCastPath &Path) { + for (auto I = CE->path_begin(), E = CE->path_end(); I != E; ++I) { + if (CXXBaseSpecifier *Spec = Importer.Import(*I)) + Path.push_back(Spec); + else + return true; + } + return false; } Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) { @@ -5787,7 +6040,7 @@ Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) { SubExpr, &BasePath, E->getValueKind()); } -Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) { +Expr *ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) return nullptr; @@ -5804,11 +6057,320 @@ Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) { if (ImportCastPath(E, BasePath)) return nullptr; - return CStyleCastExpr::Create(Importer.getToContext(), T, - E->getValueKind(), E->getCastKind(), - SubExpr, &BasePath, TInfo, - Importer.Import(E->getLParenLoc()), - Importer.Import(E->getRParenLoc())); + switch (E->getStmtClass()) { + case Stmt::CStyleCastExprClass: { + CStyleCastExpr *CCE = cast<CStyleCastExpr>(E); + return CStyleCastExpr::Create(Importer.getToContext(), T, + E->getValueKind(), E->getCastKind(), + SubExpr, &BasePath, TInfo, + Importer.Import(CCE->getLParenLoc()), + Importer.Import(CCE->getRParenLoc())); + } + + case Stmt::CXXFunctionalCastExprClass: { + CXXFunctionalCastExpr *FCE = cast<CXXFunctionalCastExpr>(E); + return CXXFunctionalCastExpr::Create(Importer.getToContext(), T, + E->getValueKind(), TInfo, + E->getCastKind(), SubExpr, &BasePath, + Importer.Import(FCE->getLParenLoc()), + Importer.Import(FCE->getRParenLoc())); + } + + case Stmt::ObjCBridgedCastExprClass: { + ObjCBridgedCastExpr *OCE = cast<ObjCBridgedCastExpr>(E); + return new (Importer.getToContext()) ObjCBridgedCastExpr( + Importer.Import(OCE->getLParenLoc()), OCE->getBridgeKind(), + E->getCastKind(), Importer.Import(OCE->getBridgeKeywordLoc()), + TInfo, SubExpr); + } + default: + break; // just fall through + } + + CXXNamedCastExpr *Named = cast<CXXNamedCastExpr>(E); + SourceLocation ExprLoc = Importer.Import(Named->getOperatorLoc()), + RParenLoc = Importer.Import(Named->getRParenLoc()); + SourceRange Brackets = Importer.Import(Named->getAngleBrackets()); + + switch (E->getStmtClass()) { + case Stmt::CXXStaticCastExprClass: + return CXXStaticCastExpr::Create(Importer.getToContext(), T, + E->getValueKind(), E->getCastKind(), + SubExpr, &BasePath, TInfo, + ExprLoc, RParenLoc, Brackets); + + case Stmt::CXXDynamicCastExprClass: + return CXXDynamicCastExpr::Create(Importer.getToContext(), T, + E->getValueKind(), E->getCastKind(), + SubExpr, &BasePath, TInfo, + ExprLoc, RParenLoc, Brackets); + + case Stmt::CXXReinterpretCastExprClass: + return CXXReinterpretCastExpr::Create(Importer.getToContext(), T, + E->getValueKind(), E->getCastKind(), + SubExpr, &BasePath, TInfo, + ExprLoc, RParenLoc, Brackets); + + case Stmt::CXXConstCastExprClass: + return CXXConstCastExpr::Create(Importer.getToContext(), T, + E->getValueKind(), SubExpr, TInfo, ExprLoc, + RParenLoc, Brackets); + default: + llvm_unreachable("Cast expression of unsupported type!"); + return nullptr; + } +} + +Expr *ASTNodeImporter::VisitOffsetOfExpr(OffsetOfExpr *OE) { + QualType T = Importer.Import(OE->getType()); + if (T.isNull()) + return nullptr; + + SmallVector<OffsetOfNode, 4> Nodes; + for (int I = 0, E = OE->getNumComponents(); I < E; ++I) { + const OffsetOfNode &Node = OE->getComponent(I); + + switch (Node.getKind()) { + case OffsetOfNode::Array: + Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()), + Node.getArrayExprIndex(), + Importer.Import(Node.getLocEnd()))); + break; + + case OffsetOfNode::Base: { + CXXBaseSpecifier *BS = Importer.Import(Node.getBase()); + if (!BS && Node.getBase()) + return nullptr; + Nodes.push_back(OffsetOfNode(BS)); + break; + } + case OffsetOfNode::Field: { + FieldDecl *FD = cast_or_null<FieldDecl>(Importer.Import(Node.getField())); + if (!FD) + return nullptr; + Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()), FD, + Importer.Import(Node.getLocEnd()))); + break; + } + case OffsetOfNode::Identifier: { + IdentifierInfo *ToII = Importer.Import(Node.getFieldName()); + if (!ToII) + return nullptr; + Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()), ToII, + Importer.Import(Node.getLocEnd()))); + break; + } + } + } + + SmallVector<Expr *, 4> Exprs(OE->getNumExpressions()); + for (int I = 0, E = OE->getNumExpressions(); I < E; ++I) { + Expr *ToIndexExpr = Importer.Import(OE->getIndexExpr(I)); + if (!ToIndexExpr) + return nullptr; + Exprs[I] = ToIndexExpr; + } + + TypeSourceInfo *TInfo = Importer.Import(OE->getTypeSourceInfo()); + if (!TInfo && OE->getTypeSourceInfo()) + return nullptr; + + return OffsetOfExpr::Create(Importer.getToContext(), T, + Importer.Import(OE->getOperatorLoc()), + TInfo, Nodes, Exprs, + Importer.Import(OE->getRParenLoc())); +} + +Expr *ASTNodeImporter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *Operand = Importer.Import(E->getOperand()); + if (!Operand) + return nullptr; + + CanThrowResult CanThrow; + if (E->isValueDependent()) + CanThrow = CT_Dependent; + else + CanThrow = E->getValue() ? CT_Can : CT_Cannot; + + return new (Importer.getToContext()) CXXNoexceptExpr( + T, Operand, CanThrow, + Importer.Import(E->getLocStart()), Importer.Import(E->getLocEnd())); +} + +Expr *ASTNodeImporter::VisitCXXThrowExpr(CXXThrowExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *SubExpr = Importer.Import(E->getSubExpr()); + if (!SubExpr && E->getSubExpr()) + return nullptr; + + return new (Importer.getToContext()) CXXThrowExpr( + SubExpr, T, Importer.Import(E->getThrowLoc()), + E->isThrownVariableInScope()); +} + +Expr *ASTNodeImporter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { + ParmVarDecl *Param = cast_or_null<ParmVarDecl>( + Importer.Import(E->getParam())); + if (!Param) + return nullptr; + + return CXXDefaultArgExpr::Create( + Importer.getToContext(), Importer.Import(E->getUsedLocation()), Param); +} + +Expr *ASTNodeImporter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + TypeSourceInfo *TypeInfo = Importer.Import(E->getTypeSourceInfo()); + if (!TypeInfo) + return nullptr; + + return new (Importer.getToContext()) CXXScalarValueInitExpr( + T, TypeInfo, Importer.Import(E->getRParenLoc())); +} + +Expr *ASTNodeImporter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { + Expr *SubExpr = Importer.Import(E->getSubExpr()); + if (!SubExpr) + return nullptr; + + auto *Dtor = cast_or_null<CXXDestructorDecl>( + Importer.Import(const_cast<CXXDestructorDecl *>( + E->getTemporary()->getDestructor()))); + if (!Dtor) + return nullptr; + + ASTContext &ToCtx = Importer.getToContext(); + CXXTemporary *Temp = CXXTemporary::Create(ToCtx, Dtor); + return CXXBindTemporaryExpr::Create(ToCtx, Temp, SubExpr); +} + +Expr *ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE) { + QualType T = Importer.Import(CE->getType()); + if (T.isNull()) + return nullptr; + + SmallVector<Expr *, 8> Args(CE->getNumArgs()); + if (ImportContainerChecked(CE->arguments(), Args)) + return nullptr; + + auto *Ctor = cast_or_null<CXXConstructorDecl>( + Importer.Import(CE->getConstructor())); + if (!Ctor) + return nullptr; + + return CXXTemporaryObjectExpr::Create( + Importer.getToContext(), T, + Importer.Import(CE->getLocStart()), + Ctor, + CE->isElidable(), + Args, + CE->hadMultipleCandidates(), + CE->isListInitialization(), + CE->isStdInitListInitialization(), + CE->requiresZeroInitialization(), + CE->getConstructionKind(), + Importer.Import(CE->getParenOrBraceRange())); +} + +Expr * +ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *TempE = Importer.Import(E->GetTemporaryExpr()); + if (!TempE) + return nullptr; + + ValueDecl *ExtendedBy = cast_or_null<ValueDecl>( + Importer.Import(const_cast<ValueDecl *>(E->getExtendingDecl()))); + if (!ExtendedBy && E->getExtendingDecl()) + return nullptr; + + auto *ToMTE = new (Importer.getToContext()) MaterializeTemporaryExpr( + T, TempE, E->isBoundToLvalueReference()); + + // FIXME: Should ManglingNumber get numbers associated with 'to' context? + ToMTE->setExtendingDecl(ExtendedBy, E->getManglingNumber()); + return ToMTE; +} + +Expr *ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *CE) { + QualType T = Importer.Import(CE->getType()); + if (T.isNull()) + return nullptr; + + SmallVector<Expr *, 4> PlacementArgs(CE->getNumPlacementArgs()); + if (ImportContainerChecked(CE->placement_arguments(), PlacementArgs)) + return nullptr; + + FunctionDecl *OperatorNewDecl = cast_or_null<FunctionDecl>( + Importer.Import(CE->getOperatorNew())); + if (!OperatorNewDecl && CE->getOperatorNew()) + return nullptr; + + FunctionDecl *OperatorDeleteDecl = cast_or_null<FunctionDecl>( + Importer.Import(CE->getOperatorDelete())); + if (!OperatorDeleteDecl && CE->getOperatorDelete()) + return nullptr; + + Expr *ToInit = Importer.Import(CE->getInitializer()); + if (!ToInit && CE->getInitializer()) + return nullptr; + + TypeSourceInfo *TInfo = Importer.Import(CE->getAllocatedTypeSourceInfo()); + if (!TInfo) + return nullptr; + + Expr *ToArrSize = Importer.Import(CE->getArraySize()); + if (!ToArrSize && CE->getArraySize()) + return nullptr; + + return new (Importer.getToContext()) CXXNewExpr( + Importer.getToContext(), + CE->isGlobalNew(), + OperatorNewDecl, OperatorDeleteDecl, + CE->passAlignment(), + CE->doesUsualArrayDeleteWantSize(), + PlacementArgs, + Importer.Import(CE->getTypeIdParens()), + ToArrSize, CE->getInitializationStyle(), ToInit, T, TInfo, + Importer.Import(CE->getSourceRange()), + Importer.Import(CE->getDirectInitRange())); +} + +Expr *ASTNodeImporter::VisitCXXDeleteExpr(CXXDeleteExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + FunctionDecl *OperatorDeleteDecl = cast_or_null<FunctionDecl>( + Importer.Import(E->getOperatorDelete())); + if (!OperatorDeleteDecl && E->getOperatorDelete()) + return nullptr; + + Expr *ToArg = Importer.Import(E->getArgument()); + if (!ToArg && E->getArgument()) + return nullptr; + + return new (Importer.getToContext()) CXXDeleteExpr( + T, E->isGlobalDelete(), + E->isArrayForm(), + E->isArrayFormAsWritten(), + E->doesUsualArrayDeleteWantSize(), + OperatorDeleteDecl, + ToArg, + Importer.Import(E->getLocStart())); } Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) { @@ -5822,8 +6384,7 @@ Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) { return nullptr; SmallVector<Expr *, 6> ToArgs(E->getNumArgs()); - if (ImportArrayChecked(E->getArgs(), E->getArgs() + E->getNumArgs(), - ToArgs.begin())) + if (ImportContainerChecked(E->arguments(), ToArgs)) return nullptr; return CXXConstructExpr::Create(Importer.getToContext(), T, @@ -5837,6 +6398,24 @@ Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) { Importer.Import(E->getParenOrBraceRange())); } +Expr *ASTNodeImporter::VisitExprWithCleanups(ExprWithCleanups *EWC) { + Expr *SubExpr = Importer.Import(EWC->getSubExpr()); + if (!SubExpr && EWC->getSubExpr()) + return nullptr; + + SmallVector<ExprWithCleanups::CleanupObject, 8> Objs(EWC->getNumObjects()); + for (unsigned I = 0, E = EWC->getNumObjects(); I < E; I++) + if (ExprWithCleanups::CleanupObject Obj = + cast_or_null<BlockDecl>(Importer.Import(EWC->getObject(I)))) + Objs[I] = Obj; + else + return nullptr; + + return ExprWithCleanups::Create(Importer.getToContext(), + SubExpr, EWC->cleanupsHaveSideEffects(), + Objs); +} + Expr *ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) @@ -5847,8 +6426,7 @@ Expr *ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { return nullptr; SmallVector<Expr *, 4> ToArgs(E->getNumArgs()); - - if (ImportArrayChecked(E->arg_begin(), E->arg_end(), ToArgs.begin())) + if (ImportContainerChecked(E->arguments(), ToArgs)) return nullptr; return new (Importer.getToContext()) CXXMemberCallExpr( @@ -5949,8 +6527,7 @@ Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) { return nullptr; llvm::SmallVector<Expr *, 4> Exprs(ILE->getNumInits()); - if (ImportArrayChecked( - ILE->getInits(), ILE->getInits() + ILE->getNumInits(), Exprs.begin())) + if (ImportContainerChecked(ILE->inits(), Exprs)) return nullptr; ASTContext &ToCtx = Importer.getToContext(); @@ -5988,6 +6565,30 @@ Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) { return To; } +Expr *ASTNodeImporter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) { + QualType ToType = Importer.Import(E->getType()); + if (ToType.isNull()) + return nullptr; + + Expr *ToCommon = Importer.Import(E->getCommonExpr()); + if (!ToCommon && E->getCommonExpr()) + return nullptr; + + Expr *ToSubExpr = Importer.Import(E->getSubExpr()); + if (!ToSubExpr && E->getSubExpr()) + return nullptr; + + return new (Importer.getToContext()) + ArrayInitLoopExpr(ToType, ToCommon, ToSubExpr); +} + +Expr *ASTNodeImporter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) { + QualType ToType = Importer.Import(E->getType()); + if (ToType.isNull()) + return nullptr; + return new (Importer.getToContext()) ArrayInitIndexExpr(ToType); +} + Expr *ASTNodeImporter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) { FieldDecl *ToField = llvm::dyn_cast_or_null<FieldDecl>( Importer.Import(DIE->getField())); @@ -6376,10 +6977,10 @@ SourceLocation ASTImporter::Import(SourceLocation FromLoc) { SourceManager &FromSM = FromContext.getSourceManager(); - // For now, map everything down to its spelling location, so that we + // For now, map everything down to its file location, so that we // don't have to import macro expansions. // FIXME: Import macro expansions! - FromLoc = FromSM.getSpellingLoc(FromLoc); + FromLoc = FromSM.getFileLoc(FromLoc); std::pair<FileID, unsigned> Decomposed = FromSM.getDecomposedLoc(FromLoc); SourceManager &ToSM = ToContext.getSourceManager(); FileID ToFileID = Import(Decomposed.first); @@ -6478,31 +7079,27 @@ CXXCtorInitializer *ASTImporter::Import(CXXCtorInitializer *From) { return new (ToContext) CXXCtorInitializer(ToContext, ToTInfo, Import(From->getLParenLoc()), ToExpr, Import(From->getRParenLoc())); - } else if (unsigned NumArrayIndices = From->getNumArrayIndices()) { - FieldDecl *ToField = - llvm::cast_or_null<FieldDecl>(Import(From->getMember())); - if (!ToField && From->getMember()) - return nullptr; - - SmallVector<VarDecl *, 4> ToAIs(NumArrayIndices); - - for (unsigned AII = 0; AII < NumArrayIndices; ++AII) { - VarDecl *ToArrayIndex = - dyn_cast_or_null<VarDecl>(Import(From->getArrayIndex(AII))); - if (!ToArrayIndex && From->getArrayIndex(AII)) - return nullptr; - } - - return CXXCtorInitializer::Create( - ToContext, ToField, Import(From->getMemberLocation()), - Import(From->getLParenLoc()), ToExpr, Import(From->getRParenLoc()), - ToAIs.data(), NumArrayIndices); } else { return nullptr; } } +CXXBaseSpecifier *ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) { + auto Pos = ImportedCXXBaseSpecifiers.find(BaseSpec); + if (Pos != ImportedCXXBaseSpecifiers.end()) + return Pos->second; + + CXXBaseSpecifier *Imported = new (ToContext) CXXBaseSpecifier( + Import(BaseSpec->getSourceRange()), + BaseSpec->isVirtual(), BaseSpec->isBaseOfClass(), + BaseSpec->getAccessSpecifierAsWritten(), + Import(BaseSpec->getTypeSourceInfo()), + Import(BaseSpec->getEllipsisLoc())); + ImportedCXXBaseSpecifiers[BaseSpec] = Imported; + return Imported; +} + void ASTImporter::ImportDefinition(Decl *From) { Decl *To = Import(From); if (!To) diff --git a/contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp b/contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp index 2336c98..461084c 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp @@ -23,6 +23,7 @@ namespace ast_type_traits { const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = { { NKI_None, "<None>" }, { NKI_None, "TemplateArgument" }, + { NKI_None, "TemplateName" }, { NKI_None, "NestedNameSpecifierLoc" }, { NKI_None, "QualType" }, { NKI_None, "TypeLoc" }, @@ -109,6 +110,8 @@ void DynTypedNode::print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const { if (const TemplateArgument *TA = get<TemplateArgument>()) TA->print(PP, OS); + else if (const TemplateName *TN = get<TemplateName>()) + TN->print(OS, PP); else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>()) NNS->print(OS, PP); else if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>()) @@ -132,6 +135,8 @@ void DynTypedNode::dump(llvm::raw_ostream &OS, SourceManager &SM) const { D->dump(OS); else if (const Stmt *S = get<Stmt>()) S->dump(OS, SM); + else if (const Type *T = get<Type>()) + T->dump(OS); else OS << "Unable to dump values of type " << NodeKind.asStringRef() << "\n"; } diff --git a/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp b/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp index cb60870..b06b50c 100644 --- a/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp @@ -11,11 +11,10 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/Attr.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" #include "clang/AST/Expr.h" #include "clang/AST/Type.h" -#include "llvm/ADT/StringSwitch.h" using namespace clang; #include "clang/AST/AttrImpl.inc" diff --git a/contrib/llvm/tools/clang/lib/AST/CXXABI.h b/contrib/llvm/tools/clang/lib/AST/CXXABI.h index c23b919..924ef00 100644 --- a/contrib/llvm/tools/clang/lib/AST/CXXABI.h +++ b/contrib/llvm/tools/clang/lib/AST/CXXABI.h @@ -43,7 +43,8 @@ public: virtual bool isNearlyEmpty(const CXXRecordDecl *RD) const = 0; /// Returns a new mangling number context for this C++ ABI. - virtual MangleNumberingContext *createMangleNumberingContext() const = 0; + virtual std::unique_ptr<MangleNumberingContext> + createMangleNumberingContext() const = 0; /// Adds a mapping from class to copy constructor for this C++ ABI. virtual void addCopyConstructorForExceptionObject(CXXRecordDecl *, @@ -53,12 +54,6 @@ public: virtual const CXXConstructorDecl * getCopyConstructorForExceptionObject(CXXRecordDecl *) = 0; - virtual void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD, - unsigned ParmIdx, Expr *DAE) = 0; - - virtual Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, - unsigned ParmIdx) = 0; - virtual void addTypedefNameForUnnamedTagDecl(TagDecl *TD, TypedefNameDecl *DD) = 0; diff --git a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp index 6a6ca76..a97d6a2 100644 --- a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp @@ -16,7 +16,6 @@ #include "clang/AST/RecordLayout.h" #include "llvm/ADT/SetVector.h" #include <algorithm> -#include <set> using namespace clang; diff --git a/contrib/llvm/tools/clang/lib/AST/Comment.cpp b/contrib/llvm/tools/clang/lib/AST/Comment.cpp index 893bdc5..7a7d3dd 100644 --- a/contrib/llvm/tools/clang/lib/AST/Comment.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Comment.cpp @@ -7,14 +7,13 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/ASTContext.h" #include "clang/AST/Comment.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/Basic/CharInfo.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" namespace clang { namespace comments { @@ -114,6 +113,65 @@ bool ParagraphComment::isWhitespaceNoCache() const { return true; } +static TypeLoc lookThroughTypedefOrTypeAliasLocs(TypeLoc &SrcTL) { + TypeLoc TL = SrcTL.IgnoreParens(); + + // Look through qualified types. + if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) + return QualifiedTL.getUnqualifiedLoc(); + // Look through pointer types. + if (PointerTypeLoc PointerTL = TL.getAs<PointerTypeLoc>()) + return PointerTL.getPointeeLoc().getUnqualifiedLoc(); + // Look through reference types. + if (ReferenceTypeLoc ReferenceTL = TL.getAs<ReferenceTypeLoc>()) + return ReferenceTL.getPointeeLoc().getUnqualifiedLoc(); + // Look through adjusted types. + if (AdjustedTypeLoc ATL = TL.getAs<AdjustedTypeLoc>()) + return ATL.getOriginalLoc(); + if (BlockPointerTypeLoc BlockPointerTL = TL.getAs<BlockPointerTypeLoc>()) + return BlockPointerTL.getPointeeLoc().getUnqualifiedLoc(); + if (MemberPointerTypeLoc MemberPointerTL = TL.getAs<MemberPointerTypeLoc>()) + return MemberPointerTL.getPointeeLoc().getUnqualifiedLoc(); + if (ElaboratedTypeLoc ETL = TL.getAs<ElaboratedTypeLoc>()) + return ETL.getNamedTypeLoc(); + + return TL; +} + +static bool getFunctionTypeLoc(TypeLoc TL, FunctionTypeLoc &ResFTL) { + TypeLoc PrevTL; + while (PrevTL != TL) { + PrevTL = TL; + TL = lookThroughTypedefOrTypeAliasLocs(TL); + } + + if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { + ResFTL = FTL; + return true; + } + + if (TemplateSpecializationTypeLoc STL = + TL.getAs<TemplateSpecializationTypeLoc>()) { + // If we have a typedef to a template specialization with exactly one + // template argument of a function type, this looks like std::function, + // boost::function, or other function wrapper. Treat these typedefs as + // functions. + if (STL.getNumArgs() != 1) + return false; + TemplateArgumentLoc MaybeFunction = STL.getArgLoc(0); + if (MaybeFunction.getArgument().getKind() != TemplateArgument::Type) + return false; + TypeSourceInfo *MaybeFunctionTSI = MaybeFunction.getTypeSourceInfo(); + TypeLoc TL = MaybeFunctionTSI->getTypeLoc().getUnqualifiedLoc(); + if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { + ResFTL = FTL; + return true; + } + } + + return false; +} + const char *ParamCommandComment::getDirectionAsString(PassDirection D) { switch (D) { case ParamCommandComment::In: @@ -227,90 +285,45 @@ void DeclInfo::fill() { case Decl::Namespace: Kind = NamespaceKind; break; + case Decl::TypeAlias: case Decl::Typedef: { Kind = TypedefKind; - // If this is a typedef to something we consider a function, extract + // If this is a typedef / using to something we consider a function, extract // arguments and return type. - const TypedefDecl *TD = cast<TypedefDecl>(CommentDecl); - const TypeSourceInfo *TSI = TD->getTypeSourceInfo(); + const TypeSourceInfo *TSI = + K == Decl::Typedef + ? cast<TypedefDecl>(CommentDecl)->getTypeSourceInfo() + : cast<TypeAliasDecl>(CommentDecl)->getTypeSourceInfo(); if (!TSI) break; TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc(); - while (true) { - TL = TL.IgnoreParens(); - // Look through qualified types. - if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) { - TL = QualifiedTL.getUnqualifiedLoc(); - continue; - } - // Look through pointer types. - if (PointerTypeLoc PointerTL = TL.getAs<PointerTypeLoc>()) { - TL = PointerTL.getPointeeLoc().getUnqualifiedLoc(); - continue; - } - // Look through reference types. - if (ReferenceTypeLoc ReferenceTL = TL.getAs<ReferenceTypeLoc>()) { - TL = ReferenceTL.getPointeeLoc().getUnqualifiedLoc(); - continue; - } - // Look through adjusted types. - if (AdjustedTypeLoc ATL = TL.getAs<AdjustedTypeLoc>()) { - TL = ATL.getOriginalLoc(); - continue; - } - if (BlockPointerTypeLoc BlockPointerTL = - TL.getAs<BlockPointerTypeLoc>()) { - TL = BlockPointerTL.getPointeeLoc().getUnqualifiedLoc(); - continue; - } - if (MemberPointerTypeLoc MemberPointerTL = - TL.getAs<MemberPointerTypeLoc>()) { - TL = MemberPointerTL.getPointeeLoc().getUnqualifiedLoc(); - continue; - } - if (ElaboratedTypeLoc ETL = TL.getAs<ElaboratedTypeLoc>()) { - TL = ETL.getNamedTypeLoc(); - continue; - } - // Is this a typedef for a function type? - if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { - Kind = FunctionKind; - ParamVars = FTL.getParams(); - ReturnType = FTL.getReturnLoc().getType(); - break; - } - if (TemplateSpecializationTypeLoc STL = - TL.getAs<TemplateSpecializationTypeLoc>()) { - // If we have a typedef to a template specialization with exactly one - // template argument of a function type, this looks like std::function, - // boost::function, or other function wrapper. Treat these typedefs as - // functions. - if (STL.getNumArgs() != 1) - break; - TemplateArgumentLoc MaybeFunction = STL.getArgLoc(0); - if (MaybeFunction.getArgument().getKind() != TemplateArgument::Type) - break; - TypeSourceInfo *MaybeFunctionTSI = MaybeFunction.getTypeSourceInfo(); - TypeLoc TL = MaybeFunctionTSI->getTypeLoc().getUnqualifiedLoc(); - if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { - Kind = FunctionKind; - ParamVars = FTL.getParams(); - ReturnType = FTL.getReturnLoc().getType(); - } - break; - } - break; + FunctionTypeLoc FTL; + if (getFunctionTypeLoc(TL, FTL)) { + Kind = FunctionKind; + ParamVars = FTL.getParams(); + ReturnType = FTL.getReturnLoc().getType(); } break; } - case Decl::TypeAlias: - Kind = TypedefKind; - break; case Decl::TypeAliasTemplate: { const TypeAliasTemplateDecl *TAT = cast<TypeAliasTemplateDecl>(CommentDecl); Kind = TypedefKind; TemplateKind = Template; TemplateParameters = TAT->getTemplateParameters(); + TypeAliasDecl *TAD = TAT->getTemplatedDecl(); + if (!TAD) + break; + + const TypeSourceInfo *TSI = TAD->getTypeSourceInfo(); + if (!TSI) + break; + TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc(); + FunctionTypeLoc FTL; + if (getFunctionTypeLoc(TL, FTL)) { + Kind = FunctionKind; + ParamVars = FTL.getParams(); + ReturnType = FTL.getReturnLoc().getType(); + } break; } case Decl::Enum: diff --git a/contrib/llvm/tools/clang/lib/AST/CommentBriefParser.cpp b/contrib/llvm/tools/clang/lib/AST/CommentBriefParser.cpp index 090b921..eecea8f 100644 --- a/contrib/llvm/tools/clang/lib/AST/CommentBriefParser.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CommentBriefParser.cpp @@ -9,7 +9,6 @@ #include "clang/AST/CommentBriefParser.h" #include "clang/AST/CommentCommandTraits.h" -#include "llvm/ADT/StringSwitch.h" namespace clang { namespace comments { diff --git a/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp b/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp index 57bfef0..65d0f56 100644 --- a/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp @@ -378,15 +378,17 @@ void Lexer::lexCommentText(Token &T) { if ((Info = Traits.getTypoCorrectCommandInfo(CommandName))) { StringRef CorrectedName = Info->Name; SourceLocation Loc = getSourceLocation(BufferPtr); - SourceRange CommandRange(Loc.getLocWithOffset(1), - getSourceLocation(TokenPtr)); + SourceLocation EndLoc = getSourceLocation(TokenPtr); + SourceRange FullRange = SourceRange(Loc, EndLoc); + SourceRange CommandRange(Loc.getLocWithOffset(1), EndLoc); Diag(Loc, diag::warn_correct_comment_command_name) - << CommandName << CorrectedName + << FullRange << CommandName << CorrectedName << FixItHint::CreateReplacement(CommandRange, CorrectedName); } else { formTokenWithChars(T, TokenPtr, tok::unknown_command); T.setUnknownCommandName(CommandName); - Diag(T.getLocation(), diag::warn_unknown_comment_command_name); + Diag(T.getLocation(), diag::warn_unknown_comment_command_name) + << SourceRange(T.getLocation(), T.getEndLocation()); return; } } diff --git a/contrib/llvm/tools/clang/lib/AST/CommentParser.cpp b/contrib/llvm/tools/clang/lib/AST/CommentParser.cpp index cb37ec3..c1c0423 100644 --- a/contrib/llvm/tools/clang/lib/AST/CommentParser.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CommentParser.cpp @@ -40,11 +40,11 @@ class TextTokenRetokenizer { /// A position in \c Toks. struct Position { - unsigned CurToken; const char *BufferStart; const char *BufferEnd; const char *BufferPtr; SourceLocation BufferStartLoc; + unsigned CurToken; }; /// Current position in Toks. diff --git a/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp b/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp index f5f4f70..d39a9b2 100644 --- a/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp @@ -950,20 +950,19 @@ unsigned Sema::resolveParmVarReference(StringRef Name, namespace { class SimpleTypoCorrector { + const NamedDecl *BestDecl; + StringRef Typo; const unsigned MaxEditDistance; - const NamedDecl *BestDecl; unsigned BestEditDistance; unsigned BestIndex; unsigned NextIndex; public: - SimpleTypoCorrector(StringRef Typo) : - Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3), - BestDecl(nullptr), BestEditDistance(MaxEditDistance + 1), - BestIndex(0), NextIndex(0) - { } + explicit SimpleTypoCorrector(StringRef Typo) + : BestDecl(nullptr), Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3), + BestEditDistance(MaxEditDistance + 1), BestIndex(0), NextIndex(0) {} void addDecl(const NamedDecl *ND); diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp index d1e8d25..81f0878 100644 --- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp @@ -1395,6 +1395,10 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, return clang::LinkageComputer::getLVForDecl(D, computation); } +void NamedDecl::printName(raw_ostream &os) const { + os << Name; +} + std::string NamedDecl::getQualifiedNameAsString() const { std::string QualName; llvm::raw_string_ostream OS(QualName); @@ -1481,7 +1485,7 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, OS << "::"; } - if (getDeclName()) + if (getDeclName() || isa<DecompositionDecl>(this)) OS << *this; else OS << "(anonymous)"; @@ -1922,6 +1926,9 @@ VarDecl::isThisDeclarationADefinition(ASTContext &C) const { // // FIXME: How do you declare (but not define) a partial specialization of // a static data member template outside the containing class? + if (isThisDeclarationADemotedDefinition()) + return DeclarationOnly; + if (isStaticDataMember()) { if (isOutOfLine() && !(getCanonicalDecl()->isInline() && @@ -2246,6 +2253,56 @@ bool VarDecl::checkInitIsICE() const { return Eval->IsICE; } +VarDecl *VarDecl::getTemplateInstantiationPattern() const { + // If it's a variable template specialization, find the template or partial + // specialization from which it was instantiated. + if (auto *VDTemplSpec = dyn_cast<VarTemplateSpecializationDecl>(this)) { + auto From = VDTemplSpec->getInstantiatedFrom(); + if (auto *VTD = From.dyn_cast<VarTemplateDecl *>()) { + while (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate()) { + if (NewVTD->isMemberSpecialization()) + break; + VTD = NewVTD; + } + return VTD->getTemplatedDecl()->getDefinition(); + } + if (auto *VTPSD = + From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) { + while (auto *NewVTPSD = VTPSD->getInstantiatedFromMember()) { + if (NewVTPSD->isMemberSpecialization()) + break; + VTPSD = NewVTPSD; + } + return VTPSD->getDefinition(); + } + } + + if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) { + if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) { + VarDecl *VD = getInstantiatedFromStaticDataMember(); + while (auto *NewVD = VD->getInstantiatedFromStaticDataMember()) + VD = NewVD; + return VD->getDefinition(); + } + } + + if (VarTemplateDecl *VarTemplate = getDescribedVarTemplate()) { + + while (VarTemplate->getInstantiatedFromMemberTemplate()) { + if (VarTemplate->isMemberSpecialization()) + break; + VarTemplate = VarTemplate->getInstantiatedFromMemberTemplate(); + } + + assert((!VarTemplate->getTemplatedDecl() || + !isTemplateInstantiation(getTemplateSpecializationKind())) && + "couldn't find pattern for variable instantiation"); + + return VarTemplate->getTemplatedDecl(); + } + return nullptr; +} + VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const { if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) return cast<VarDecl>(MSI->getInstantiatedFrom()); @@ -2592,7 +2649,7 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { return false; const auto *FPT = getType()->castAs<FunctionProtoType>(); - if (FPT->getNumParams() == 0 || FPT->getNumParams() > 2 || FPT->isVariadic()) + if (FPT->getNumParams() == 0 || FPT->getNumParams() > 3 || FPT->isVariadic()) return false; // If this is a single-parameter function, it must be a replaceable global @@ -2600,20 +2657,42 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { if (FPT->getNumParams() == 1) return true; - // Otherwise, we're looking for a second parameter whose type is - // 'const std::nothrow_t &', or, in C++1y, 'std::size_t'. - QualType Ty = FPT->getParamType(1); + unsigned Params = 1; + QualType Ty = FPT->getParamType(Params); ASTContext &Ctx = getASTContext(); + + auto Consume = [&] { + ++Params; + Ty = Params < FPT->getNumParams() ? FPT->getParamType(Params) : QualType(); + }; + + // In C++14, the next parameter can be a 'std::size_t' for sized delete. + bool IsSizedDelete = false; if (Ctx.getLangOpts().SizedDeallocation && - Ctx.hasSameType(Ty, Ctx.getSizeType())) - return true; - if (!Ty->isReferenceType()) - return false; - Ty = Ty->getPointeeType(); - if (Ty.getCVRQualifiers() != Qualifiers::Const) - return false; - const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); - return RD && isNamed(RD, "nothrow_t") && RD->isInStdNamespace(); + (getDeclName().getCXXOverloadedOperator() == OO_Delete || + getDeclName().getCXXOverloadedOperator() == OO_Array_Delete) && + Ctx.hasSameType(Ty, Ctx.getSizeType())) { + IsSizedDelete = true; + Consume(); + } + + // 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()) + Consume(); + + // Finally, if this is not a sized delete, the final parameter can + // be a 'const std::nothrow_t&'. + if (!IsSizedDelete && !Ty.isNull() && Ty->isReferenceType()) { + Ty = Ty->getPointeeType(); + if (Ty.getCVRQualifiers() != Qualifiers::Const) + return false; + const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); + if (RD && isNamed(RD, "nothrow_t") && RD->isInStdNamespace()) + Consume(); + } + + return Params == FPT->getNumParams(); } LanguageLinkage FunctionDecl::getLanguageLinkage() const { @@ -2653,9 +2732,14 @@ bool FunctionDecl::isGlobal() const { } bool FunctionDecl::isNoReturn() const { - return hasAttr<NoReturnAttr>() || hasAttr<CXX11NoReturnAttr>() || - hasAttr<C11NoReturnAttr>() || - getType()->getAs<FunctionType>()->getNoReturnAttr(); + if (hasAttr<NoReturnAttr>() || hasAttr<CXX11NoReturnAttr>() || + hasAttr<C11NoReturnAttr>()) + return true; + + if (auto *FnTy = getType()->getAs<FunctionType>()) + return FnTy->getNoReturnAttr(); + + return false; } void @@ -2756,28 +2840,6 @@ void FunctionDecl::setParams(ASTContext &C, } } -void FunctionDecl::setDeclsInPrototypeScope(ArrayRef<NamedDecl *> NewDecls) { - assert(DeclsInPrototypeScope.empty() && "Already has prototype decls!"); - - if (!NewDecls.empty()) { - NamedDecl **A = new (getASTContext()) NamedDecl*[NewDecls.size()]; - std::copy(NewDecls.begin(), NewDecls.end(), A); - DeclsInPrototypeScope = llvm::makeArrayRef(A, NewDecls.size()); - // Move declarations introduced in prototype to the function context. - for (auto I : NewDecls) { - DeclContext *DC = I->getDeclContext(); - // Forward-declared reference to an enumeration is not added to - // declaration scope, so skip declaration that is absent from its - // declaration contexts. - if (DC->containsDecl(I)) { - DC->removeDecl(I); - I->setDeclContext(this); - addDecl(I); - } - } - } -} - /// getMinRequiredArguments - Returns the minimum number of arguments /// needed to call this function. This may be fewer than the number of /// function parameters, if some of the parameters have default @@ -2928,6 +2990,18 @@ SourceRange FunctionDecl::getReturnTypeSourceRange() const { return RTRange; } +SourceRange FunctionDecl::getExceptionSpecSourceRange() const { + const TypeSourceInfo *TSI = getTypeSourceInfo(); + if (!TSI) + return SourceRange(); + FunctionTypeLoc FTL = + TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>(); + if (!FTL) + return SourceRange(); + + return FTL.getExceptionSpecRange(); +} + const Attr *FunctionDecl::getUnusedResultAttr() const { QualType RetType = getReturnType(); if (RetType->isRecordType()) { @@ -2964,7 +3038,8 @@ const Attr *FunctionDecl::getUnusedResultAttr() const { /// an externally visible symbol, but "extern inline" will not create an /// externally visible symbol. bool FunctionDecl::isInlineDefinitionExternallyVisible() const { - assert(doesThisDeclarationHaveABody() && "Must have the function definition"); + assert((doesThisDeclarationHaveABody() || willHaveBody()) && + "Must be a function definition"); assert(isInlined() && "Function must be inline"); ASTContext &Context = getASTContext(); @@ -3408,6 +3483,10 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { case Builtin::BIstrlen: return Builtin::BIstrlen; + case Builtin::BI__builtin_bzero: + case Builtin::BIbzero: + return Builtin::BIbzero; + default: if (isExternC()) { if (FnInfo->isStr("memset")) @@ -3430,6 +3509,8 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { return Builtin::BIstrndup; else if (FnInfo->isStr("strlen")) return Builtin::BIstrlen; + else if (FnInfo->isStr("bzero")) + return Builtin::BIbzero; } break; } @@ -4281,3 +4362,18 @@ SourceRange ImportDecl::getSourceRange() const { return SourceRange(getLocation(), getIdentifierLocs().back()); } + +//===----------------------------------------------------------------------===// +// ExportDecl Implementation +//===----------------------------------------------------------------------===// + +void ExportDecl::anchor() {} + +ExportDecl *ExportDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation ExportLoc) { + return new (C, DC) ExportDecl(DC, ExportLoc); +} + +ExportDecl *ExportDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) ExportDecl(nullptr, SourceLocation()); +} diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp index bfb7d02..6111aba 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp @@ -28,7 +28,6 @@ #include "clang/AST/StmtCXX.h" #include "clang/AST/Type.h" #include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> using namespace clang; @@ -46,8 +45,7 @@ void Decl::updateOutOfDate(IdentifierInfo &II) const { } #define DECL(DERIVED, BASE) \ - static_assert(llvm::AlignOf<Decl>::Alignment >= \ - llvm::AlignOf<DERIVED##Decl>::Alignment, \ + static_assert(alignof(Decl) >= alignof(DERIVED##Decl), \ "Alignment sufficient after objects prepended to " #DERIVED); #define ABSTRACT_DECL(DECL) #include "clang/AST/DeclNodes.inc" @@ -56,7 +54,7 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Context, unsigned ID, std::size_t Extra) { // Allocate an extra 8 bytes worth of storage, which ensures that the // resulting pointer will still be 8-byte aligned. - static_assert(sizeof(unsigned) * 2 >= llvm::AlignOf<Decl>::Alignment, + static_assert(sizeof(unsigned) * 2 >= alignof(Decl), "Decl won't be misaligned"); void *Start = Context.Allocate(Size + Extra + 8); void *Result = (char*)Start + 8; @@ -81,8 +79,7 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Ctx, // Ensure required alignment of the resulting object by adding extra // padding at the start if required. size_t ExtraAlign = - llvm::OffsetToAlignment(sizeof(Module *), - llvm::AlignOf<Decl>::Alignment); + llvm::OffsetToAlignment(sizeof(Module *), alignof(Decl)); char *Buffer = reinterpret_cast<char *>( ::operator new(ExtraAlign + sizeof(Module *) + Size + Extra, Ctx)); Buffer += ExtraAlign; @@ -112,12 +109,24 @@ const char *Decl::getDeclKindName() const { void Decl::setInvalidDecl(bool Invalid) { InvalidDecl = Invalid; assert(!isa<TagDecl>(this) || !cast<TagDecl>(this)->isCompleteDefinition()); - if (Invalid && !isa<ParmVarDecl>(this)) { + if (!Invalid) { + return; + } + + if (!isa<ParmVarDecl>(this)) { // Defensive maneuver for ill-formed code: we're likely not to make it to // a point where we set the access specifier, so default it to "public" // to avoid triggering asserts elsewhere in the front end. setAccess(AS_public); } + + // Marking a DecompositionDecl as invalid implies all the child BindingDecl's + // are invalid too. + if (DecompositionDecl *DD = dyn_cast<DecompositionDecl>(this)) { + for (BindingDecl *Binding : DD->bindings()) { + Binding->setInvalidDecl(); + } + } } const char *DeclContext::getDeclKindName() const { @@ -378,6 +387,22 @@ bool Decl::isReferenced() const { return false; } +bool Decl::isExported() const { + if (isModulePrivate()) + return false; + // Namespaces are always exported. + if (isa<TranslationUnitDecl>(this) || isa<NamespaceDecl>(this)) + return true; + // Otherwise, this is a strictly lexical check. + for (auto *DC = getLexicalDeclContext(); DC; DC = DC->getLexicalParent()) { + if (cast<Decl>(DC)->isModulePrivate()) + return false; + if (isa<ExportDecl>(DC)) + return true; + } + return false; +} + bool Decl::hasDefiningAttr() const { return hasAttr<AliasAttr>() || hasAttr<IFuncAttr>(); } @@ -401,11 +426,12 @@ const Attr *Decl::getDefiningAttr() const { /// diagnostics. static AvailabilityResult CheckAvailability(ASTContext &Context, const AvailabilityAttr *A, - std::string *Message) { - VersionTuple TargetMinVersion = - Context.getTargetInfo().getPlatformMinVersion(); + std::string *Message, + VersionTuple EnclosingVersion) { + if (EnclosingVersion.empty()) + EnclosingVersion = Context.getTargetInfo().getPlatformMinVersion(); - if (TargetMinVersion.empty()) + if (EnclosingVersion.empty()) return AR_Available; // Check if this is an App Extension "platform", and if so chop off @@ -450,7 +476,7 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, // Make sure that this declaration has already been introduced. if (!A->getIntroduced().empty() && - TargetMinVersion < A->getIntroduced()) { + EnclosingVersion < A->getIntroduced()) { if (Message) { Message->clear(); llvm::raw_string_ostream Out(*Message); @@ -464,7 +490,7 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, } // Make sure that this declaration hasn't been obsoleted. - if (!A->getObsoleted().empty() && TargetMinVersion >= A->getObsoleted()) { + if (!A->getObsoleted().empty() && EnclosingVersion >= A->getObsoleted()) { if (Message) { Message->clear(); llvm::raw_string_ostream Out(*Message); @@ -478,7 +504,7 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, } // Make sure that this declaration hasn't been deprecated. - if (!A->getDeprecated().empty() && TargetMinVersion >= A->getDeprecated()) { + if (!A->getDeprecated().empty() && EnclosingVersion >= A->getDeprecated()) { if (Message) { Message->clear(); llvm::raw_string_ostream Out(*Message); @@ -494,9 +520,10 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, return AR_Available; } -AvailabilityResult Decl::getAvailability(std::string *Message) const { +AvailabilityResult Decl::getAvailability(std::string *Message, + VersionTuple EnclosingVersion) const { if (auto *FTD = dyn_cast<FunctionTemplateDecl>(this)) - return FTD->getTemplatedDecl()->getAvailability(Message); + return FTD->getTemplatedDecl()->getAvailability(Message, EnclosingVersion); AvailabilityResult Result = AR_Available; std::string ResultMessage; @@ -521,7 +548,7 @@ AvailabilityResult Decl::getAvailability(std::string *Message) const { if (const auto *Availability = dyn_cast<AvailabilityAttr>(A)) { AvailabilityResult AR = CheckAvailability(getASTContext(), Availability, - Message); + Message, EnclosingVersion); if (AR == AR_Unavailable) return AR_Unavailable; @@ -580,8 +607,8 @@ bool Decl::isWeakImported() const { return true; if (const auto *Availability = dyn_cast<AvailabilityAttr>(A)) { - if (CheckAvailability(getASTContext(), Availability, - nullptr) == AR_NotYetIntroduced) + if (CheckAvailability(getASTContext(), Availability, nullptr, + VersionTuple()) == AR_NotYetIntroduced) return true; } } @@ -599,6 +626,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case CXXConversion: case EnumConstant: case Var: + case Binding: case ImplicitParam: case ParmVar: case ObjCMethod: @@ -623,11 +651,13 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case Typedef: case TypeAlias: case TypeAliasTemplate: - case UnresolvedUsingTypename: case TemplateTypeParm: case ObjCTypeParam: return IDNS_Ordinary | IDNS_Type; + case UnresolvedUsingTypename: + return IDNS_Ordinary | IDNS_Type | IDNS_Using; + case UsingShadow: return 0; // we'll actually overwrite this later @@ -635,6 +665,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { return IDNS_Ordinary | IDNS_Using; case Using: + case UsingPack: return IDNS_Using; case ObjCProtocol: @@ -670,6 +701,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case FriendTemplate: case AccessSpec: case LinkageSpec: + case Export: case FileScopeAsm: case StaticAssert: case ObjCPropertyImpl: @@ -679,6 +711,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case Captured: case TranslationUnit: case ExternCContext: + case Decomposition: case UsingDirective: case BuiltinTemplate: @@ -954,7 +987,7 @@ bool DeclContext::isDependentContext() const { bool DeclContext::isTransparentContext() const { if (DeclKind == Decl::Enum) return !cast<EnumDecl>(this)->isScoped(); - else if (DeclKind == Decl::LinkageSpec) + else if (DeclKind == Decl::LinkageSpec || DeclKind == Decl::Export) return true; return false; @@ -974,6 +1007,18 @@ bool DeclContext::isExternCContext() const { return isLinkageSpecContext(this, clang::LinkageSpecDecl::lang_c); } +const LinkageSpecDecl *DeclContext::getExternCContext() const { + const DeclContext *DC = this; + while (DC->getDeclKind() != Decl::TranslationUnit) { + if (DC->getDeclKind() == Decl::LinkageSpec && + cast<LinkageSpecDecl>(DC)->getLanguage() == + clang::LinkageSpecDecl::lang_c) + return cast<LinkageSpecDecl>(DC); + DC = DC->getLexicalParent(); + } + return nullptr; +} + bool DeclContext::isExternCXXContext() const { return isLinkageSpecContext(this, clang::LinkageSpecDecl::lang_cxx); } @@ -993,6 +1038,7 @@ DeclContext *DeclContext::getPrimaryContext() { case Decl::TranslationUnit: case Decl::ExternCContext: case Decl::LinkageSpec: + case Decl::Export: case Decl::Block: case Decl::Captured: case Decl::OMPDeclareReduction: @@ -1405,8 +1451,8 @@ NamedDecl *const DeclContextLookupResult::SingleElementDummyList = nullptr; DeclContext::lookup_result DeclContext::lookup(DeclarationName Name) const { - assert(DeclKind != Decl::LinkageSpec && - "Should not perform lookups into linkage specs!"); + assert(DeclKind != Decl::LinkageSpec && DeclKind != Decl::Export && + "should not perform lookups into transparent contexts"); const DeclContext *PrimaryContext = getPrimaryContext(); if (PrimaryContext != this) @@ -1467,8 +1513,8 @@ DeclContext::lookup(DeclarationName Name) const { DeclContext::lookup_result DeclContext::noload_lookup(DeclarationName Name) { - assert(DeclKind != Decl::LinkageSpec && - "Should not perform lookups into linkage specs!"); + assert(DeclKind != Decl::LinkageSpec && DeclKind != Decl::Export && + "should not perform lookups into transparent contexts"); DeclContext *PrimaryContext = getPrimaryContext(); if (PrimaryContext != this) diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp index 81f9414..a9db65a 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp @@ -533,6 +533,12 @@ void CXXRecordDecl::addedMember(Decl *D) { } else if (Constructor->isMoveConstructor()) SMKind |= SMF_MoveConstructor; } + + // C++11 [dcl.init.aggr]p1: DR1518 + // An aggregate is an array or a class with no user-provided, explicit, or + // inherited constructors + if (Constructor->isUserProvided() || Constructor->isExplicit()) + data().Aggregate = false; } // Handle constructors, including those inherited from base classes. @@ -546,20 +552,6 @@ void CXXRecordDecl::addedMember(Decl *D) { // constructor [...] if (Constructor->isConstexpr() && !Constructor->isCopyOrMoveConstructor()) data().HasConstexprNonCopyMoveConstructor = true; - - // C++ [dcl.init.aggr]p1: - // An aggregate is an array or a class with no user-declared - // constructors [...]. - // C++11 [dcl.init.aggr]p1: - // An aggregate is an array or a class with no user-provided - // constructors [...]. - // C++11 [dcl.init.aggr]p1: - // An aggregate is an array or a class with no user-provided - // constructors (including those inherited from a base class) [...]. - if (getASTContext().getLangOpts().CPlusPlus11 - ? Constructor->isUserProvided() - : !Constructor->isImplicit()) - data().Aggregate = false; } // Handle destructors. @@ -739,7 +731,7 @@ void CXXRecordDecl::addedMember(Decl *D) { } if (!Field->hasInClassInitializer() && !Field->isMutable()) { - if (CXXRecordDecl *FieldType = Field->getType()->getAsCXXRecordDecl()) { + if (CXXRecordDecl *FieldType = T->getAsCXXRecordDecl()) { if (FieldType->hasDefinition() && !FieldType->allowConstDefaultInit()) data().HasUninitializedFields = true; } else { @@ -989,8 +981,12 @@ void CXXRecordDecl::addedMember(Decl *D) { if (UsingDecl *Using = dyn_cast<UsingDecl>(D)) { if (Using->getDeclName().getNameKind() == - DeclarationName::CXXConstructorName) + DeclarationName::CXXConstructorName) { data().HasInheritedConstructor = true; + // C++1z [dcl.init.aggr]p1: + // An aggregate is [...] a class [...] with no inherited constructors + data().Aggregate = false; + } if (Using->getDeclName().getCXXOverloadedOperator() == OO_Equal) data().HasInheritedAssignment = true; @@ -1107,6 +1103,12 @@ CXXRecordDecl::getGenericLambdaTemplateParameterList() const { return nullptr; } +Decl *CXXRecordDecl::getLambdaContextDecl() const { + assert(isLambda() && "Not a lambda closure type!"); + ExternalASTSource *Source = getParentASTContext().getExternalSource(); + return getLambdaData().ContextDecl.get(Source); +} + static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) { QualType T = cast<CXXConversionDecl>(Conv->getUnderlyingDecl()->getAsFunction()) @@ -1571,17 +1573,35 @@ bool CXXMethodDecl::isUsualDeallocationFunction() const { // deallocation function. [...] if (getNumParams() == 1) return true; - - // C++ [basic.stc.dynamic.deallocation]p2: + unsigned UsualParams = 1; + + // C++ <=14 [basic.stc.dynamic.deallocation]p2: // [...] If class T does not declare such an operator delete but does // declare a member deallocation function named operator delete with // exactly two parameters, the second of which has type std::size_t (18.1), // then this function is a usual deallocation function. + // + // C++17 says a usual deallocation function is one with the signature + // (void* [, size_t] [, std::align_val_t] [, ...]) + // and all such functions are usual deallocation functions. It's not clear + // that allowing varargs functions was intentional. ASTContext &Context = getASTContext(); - if (getNumParams() != 2 || - !Context.hasSameUnqualifiedType(getParamDecl(1)->getType(), - Context.getSizeType())) + if (UsualParams < getNumParams() && + Context.hasSameUnqualifiedType(getParamDecl(UsualParams)->getType(), + Context.getSizeType())) + ++UsualParams; + + if (UsualParams < getNumParams() && + getParamDecl(UsualParams)->getType()->isAlignValT()) + ++UsualParams; + + if (UsualParams != getNumParams()) return false; + + // In C++17 onwards, all potential usual deallocation functions are actual + // usual deallocation functions. + if (Context.getLangOpts().AlignedAllocation) + return true; // This function is a usual deallocation function if there are no // single-parameter deallocation functions of the same kind. @@ -1714,7 +1734,7 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, SourceLocation EllipsisLoc) : Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init), LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual), - IsWritten(false), SourceOrderOrNumArrayIndices(0) + IsWritten(false), SourceOrder(0) { } @@ -1725,7 +1745,7 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, SourceLocation R) : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), - IsWritten(false), SourceOrderOrNumArrayIndices(0) + IsWritten(false), SourceOrder(0) { } @@ -1736,7 +1756,7 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, SourceLocation R) : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), - IsWritten(false), SourceOrderOrNumArrayIndices(0) + IsWritten(false), SourceOrder(0) { } @@ -1746,38 +1766,10 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, SourceLocation R) : Initializee(TInfo), MemberOrEllipsisLocation(), Init(Init), LParenLoc(L), RParenLoc(R), IsDelegating(true), IsVirtual(false), - IsWritten(false), SourceOrderOrNumArrayIndices(0) + IsWritten(false), SourceOrder(0) { } -CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, - FieldDecl *Member, - SourceLocation MemberLoc, - SourceLocation L, Expr *Init, - SourceLocation R, - VarDecl **Indices, - unsigned NumIndices) - : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), - LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), - IsWritten(false), SourceOrderOrNumArrayIndices(NumIndices) -{ - std::uninitialized_copy(Indices, Indices + NumIndices, - getTrailingObjects<VarDecl *>()); -} - -CXXCtorInitializer *CXXCtorInitializer::Create(ASTContext &Context, - FieldDecl *Member, - SourceLocation MemberLoc, - SourceLocation L, Expr *Init, - SourceLocation R, - VarDecl **Indices, - unsigned NumIndices) { - void *Mem = Context.Allocate(totalSizeToAlloc<VarDecl *>(NumIndices), - llvm::alignOf<CXXCtorInitializer>()); - return new (Mem) CXXCtorInitializer(Context, Member, MemberLoc, L, Init, R, - Indices, NumIndices); -} - TypeLoc CXXCtorInitializer::getBaseClassLoc() const { if (isBaseInitializer()) return Initializee.get<TypeSourceInfo*>()->getTypeLoc(); @@ -2253,15 +2245,37 @@ SourceRange UsingDecl::getSourceRange() const { return SourceRange(Begin, getNameInfo().getEndLoc()); } +void UsingPackDecl::anchor() { } + +UsingPackDecl *UsingPackDecl::Create(ASTContext &C, DeclContext *DC, + NamedDecl *InstantiatedFrom, + ArrayRef<NamedDecl *> UsingDecls) { + size_t Extra = additionalSizeToAlloc<NamedDecl *>(UsingDecls.size()); + return new (C, DC, Extra) UsingPackDecl(DC, InstantiatedFrom, UsingDecls); +} + +UsingPackDecl *UsingPackDecl::CreateDeserialized(ASTContext &C, unsigned ID, + unsigned NumExpansions) { + size_t Extra = additionalSizeToAlloc<NamedDecl *>(NumExpansions); + auto *Result = new (C, ID, Extra) UsingPackDecl(nullptr, nullptr, None); + Result->NumExpansions = NumExpansions; + auto *Trail = Result->getTrailingObjects<NamedDecl *>(); + for (unsigned I = 0; I != NumExpansions; ++I) + new (Trail + I) NamedDecl*(nullptr); + return Result; +} + void UnresolvedUsingValueDecl::anchor() { } UnresolvedUsingValueDecl * UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, NestedNameSpecifierLoc QualifierLoc, - const DeclarationNameInfo &NameInfo) { + const DeclarationNameInfo &NameInfo, + SourceLocation EllipsisLoc) { return new (C, DC) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc, - QualifierLoc, NameInfo); + QualifierLoc, NameInfo, + EllipsisLoc); } UnresolvedUsingValueDecl * @@ -2269,7 +2283,8 @@ UnresolvedUsingValueDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) UnresolvedUsingValueDecl(nullptr, QualType(), SourceLocation(), NestedNameSpecifierLoc(), - DeclarationNameInfo()); + DeclarationNameInfo(), + SourceLocation()); } SourceRange UnresolvedUsingValueDecl::getSourceRange() const { @@ -2286,17 +2301,18 @@ UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation TypenameLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TargetNameLoc, - DeclarationName TargetName) { + DeclarationName TargetName, + SourceLocation EllipsisLoc) { return new (C, DC) UnresolvedUsingTypenameDecl( DC, UsingLoc, TypenameLoc, QualifierLoc, TargetNameLoc, - TargetName.getAsIdentifierInfo()); + TargetName.getAsIdentifierInfo(), EllipsisLoc); } UnresolvedUsingTypenameDecl * UnresolvedUsingTypenameDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) UnresolvedUsingTypenameDecl( nullptr, SourceLocation(), SourceLocation(), NestedNameSpecifierLoc(), - SourceLocation(), nullptr); + SourceLocation(), nullptr, SourceLocation()); } void StaticAssertDecl::anchor() { } @@ -2317,6 +2333,70 @@ StaticAssertDecl *StaticAssertDecl::CreateDeserialized(ASTContext &C, nullptr, SourceLocation(), false); } +void BindingDecl::anchor() {} + +BindingDecl *BindingDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation IdLoc, IdentifierInfo *Id) { + return new (C, DC) BindingDecl(DC, IdLoc, Id); +} + +BindingDecl *BindingDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) BindingDecl(nullptr, SourceLocation(), nullptr); +} + +VarDecl *BindingDecl::getHoldingVar() const { + Expr *B = getBinding(); + if (!B) + return nullptr; + auto *DRE = dyn_cast<DeclRefExpr>(B->IgnoreImplicit()); + if (!DRE) + return nullptr; + + auto *VD = dyn_cast<VarDecl>(DRE->getDecl()); + assert(VD->isImplicit() && "holding var for binding decl not implicit"); + return VD; +} + +void DecompositionDecl::anchor() {} + +DecompositionDecl *DecompositionDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, + SourceLocation LSquareLoc, + QualType T, TypeSourceInfo *TInfo, + StorageClass SC, + ArrayRef<BindingDecl *> Bindings) { + size_t Extra = additionalSizeToAlloc<BindingDecl *>(Bindings.size()); + return new (C, DC, Extra) + DecompositionDecl(C, DC, StartLoc, LSquareLoc, T, TInfo, SC, Bindings); +} + +DecompositionDecl *DecompositionDecl::CreateDeserialized(ASTContext &C, + unsigned ID, + unsigned NumBindings) { + size_t Extra = additionalSizeToAlloc<BindingDecl *>(NumBindings); + auto *Result = new (C, ID, Extra) + DecompositionDecl(C, nullptr, SourceLocation(), SourceLocation(), + QualType(), nullptr, StorageClass(), None); + // Set up and clean out the bindings array. + Result->NumBindings = NumBindings; + auto *Trail = Result->getTrailingObjects<BindingDecl *>(); + for (unsigned I = 0; I != NumBindings; ++I) + new (Trail + I) BindingDecl*(nullptr); + return Result; +} + +void DecompositionDecl::printName(llvm::raw_ostream &os) const { + os << '['; + bool Comma = false; + for (auto *B : bindings()) { + if (Comma) + os << ", "; + B->printName(os); + Comma = true; + } + os << ']'; +} + MSPropertyDecl *MSPropertyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, diff --git a/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp b/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp index f162e6d..2f95e1f 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp @@ -14,13 +14,12 @@ #include "clang/AST/DeclGroup.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" -#include "llvm/Support/Allocator.h" using namespace clang; DeclGroup* DeclGroup::Create(ASTContext &C, Decl **Decls, unsigned NumDecls) { assert(NumDecls > 1 && "Invalid DeclGroup"); unsigned Size = totalSizeToAlloc<Decl *>(NumDecls); - void* Mem = C.Allocate(Size, llvm::AlignOf<DeclGroup>::Alignment); + void *Mem = C.Allocate(Size, alignof(DeclGroup)); new (Mem) DeclGroup(NumDecls, Decls); return static_cast<DeclGroup*>(Mem); } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp index d270121..60d05f6 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp @@ -800,8 +800,7 @@ void ObjCMethodDecl::setParamsAndSelLocs(ASTContext &C, if (Params.empty() && SelLocs.empty()) return; - static_assert(llvm::AlignOf<ParmVarDecl *>::Alignment >= - llvm::AlignOf<SourceLocation>::Alignment, + static_assert(alignof(ParmVarDecl *) >= alignof(SourceLocation), "Alignment not sufficient for SourceLocation"); unsigned Size = sizeof(ParmVarDecl *) * NumParams + @@ -871,6 +870,12 @@ ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() { } } + // Ensure that the discovered method redeclaration has a valid declaration + // context. Used to prevent infinite loops when iterating redeclarations in + // a partially invalid AST. + if (Redecl && cast<Decl>(Redecl->getDeclContext())->isInvalidDecl()) + Redecl = nullptr; + if (!Redecl && isRedeclaration()) { // This is the last redeclaration, go back to the first method. return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(), @@ -897,9 +902,13 @@ ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() { return MD; } - if (isRedeclaration()) - return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(), - isInstanceMethod()); + if (isRedeclaration()) { + // It is possible that we have not done deserializing the ObjCMethod yet. + ObjCMethodDecl *MD = + cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(), + isInstanceMethod()); + return MD ? MD : this; + } return this; } @@ -1320,8 +1329,12 @@ ObjCTypeParamDecl *ObjCTypeParamDecl::Create(ASTContext &ctx, DeclContext *dc, IdentifierInfo *name, SourceLocation colonLoc, TypeSourceInfo *boundInfo) { - return new (ctx, dc) ObjCTypeParamDecl(ctx, dc, variance, varianceLoc, index, - nameLoc, name, colonLoc, boundInfo); + auto *TPDecl = + new (ctx, dc) ObjCTypeParamDecl(ctx, dc, variance, varianceLoc, index, + nameLoc, name, colonLoc, boundInfo); + QualType TPType = ctx.getObjCTypeParamType(TPDecl, {}); + TPDecl->setTypeForDecl(TPType.getTypePtr()); + return TPDecl; } ObjCTypeParamDecl *ObjCTypeParamDecl::CreateDeserialized(ASTContext &ctx, @@ -1366,7 +1379,7 @@ ObjCTypeParamList *ObjCTypeParamList::create( SourceLocation rAngleLoc) { void *mem = ctx.Allocate(totalSizeToAlloc<ObjCTypeParamDecl *>(typeParams.size()), - llvm::alignOf<ObjCTypeParamList>()); + alignof(ObjCTypeParamList)); return new (mem) ObjCTypeParamList(lAngleLoc, typeParams, rAngleLoc); } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp b/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp index 5b06ce0..95e44ac 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp @@ -90,13 +90,18 @@ OMPDeclareReductionDecl::getPrevDeclInScope() const { void OMPCapturedExprDecl::anchor() {} OMPCapturedExprDecl *OMPCapturedExprDecl::Create(ASTContext &C, DeclContext *DC, - IdentifierInfo *Id, - QualType T) { - return new (C, DC) OMPCapturedExprDecl(C, DC, Id, T); + IdentifierInfo *Id, QualType T, + SourceLocation StartLoc) { + return new (C, DC) OMPCapturedExprDecl(C, DC, Id, T, StartLoc); } OMPCapturedExprDecl *OMPCapturedExprDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - return new (C, ID) OMPCapturedExprDecl(C, nullptr, nullptr, QualType()); + return new (C, ID) + OMPCapturedExprDecl(C, nullptr, nullptr, QualType(), SourceLocation()); } +SourceRange OMPCapturedExprDecl::getSourceRange() const { + assert(hasInit()); + return SourceRange(getInit()->getLocStart(), getInit()->getLocEnd()); +} diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp index 7e78699..b8ebe1c 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp @@ -78,6 +78,10 @@ namespace { void VisitTemplateDecl(const TemplateDecl *D); void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); void VisitClassTemplateDecl(ClassTemplateDecl *D); + void VisitClassTemplateSpecializationDecl( + ClassTemplateSpecializationDecl *D); + void VisitClassTemplatePartialSpecializationDecl( + ClassTemplatePartialSpecializationDecl *D); void VisitObjCMethodDecl(ObjCMethodDecl *D); void VisitObjCImplementationDecl(ObjCImplementationDecl *D); void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); @@ -95,8 +99,9 @@ namespace { void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D); void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D); - void PrintTemplateParameters(const TemplateParameterList *Params, - const TemplateArgumentList *Args = nullptr); + void printTemplateParameters(const TemplateParameterList *Params); + void printTemplateArguments(const TemplateArgumentList &Args, + const TemplateParameterList *Params = nullptr); void prettyPrintAttributes(Decl *D); void prettyPrintPragmas(Decl *D); void printDeclType(QualType T, StringRef DeclName, bool Pack = false); @@ -290,6 +295,13 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { if (D->isImplicit()) continue; + // Don't print implicit specializations, as they are printed when visiting + // corresponding templates. + if (auto FD = dyn_cast<FunctionDecl>(*D)) + if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation && + !isa<ClassTemplateSpecializationDecl>(DC)) + continue; + // The next bits of code handles stuff like "struct {int x;} a,b"; we're // forced to merge the declarations because there's no other way to // refer to the struct in question. This limited merging is safe without @@ -337,12 +349,19 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { const char *Terminator = nullptr; if (isa<OMPThreadPrivateDecl>(*D) || isa<OMPDeclareReductionDecl>(*D)) Terminator = nullptr; - else if (isa<FunctionDecl>(*D) && - cast<FunctionDecl>(*D)->isThisDeclarationADefinition()) + else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->hasBody()) Terminator = nullptr; - else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody()) - Terminator = nullptr; - else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) || + else if (auto FD = dyn_cast<FunctionDecl>(*D)) { + if (FD->isThisDeclarationADefinition()) + Terminator = nullptr; + else + Terminator = ";"; + } else if (auto TD = dyn_cast<FunctionTemplateDecl>(*D)) { + if (TD->getTemplatedDecl()->isThisDeclarationADefinition()) + Terminator = nullptr; + else + Terminator = ";"; + } else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) || isa<ObjCImplementationDecl>(*D) || isa<ObjCInterfaceDecl>(*D) || isa<ObjCProtocolDecl>(*D) || @@ -359,7 +378,14 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { if (Terminator) Out << Terminator; - Out << "\n"; + if (!Policy.TerseOutput && + ((isa<FunctionDecl>(*D) && + cast<FunctionDecl>(*D)->doesThisDeclarationHaveABody()) || + (isa<FunctionTemplateDecl>(*D) && + cast<FunctionTemplateDecl>(*D)->getTemplatedDecl()->doesThisDeclarationHaveABody()))) + ; // StmtPrinter already added '\n' after CompoundStmt. + else + Out << "\n"; // Declare target attribute is special one, natural spelling for the pragma // assumes "ending" construct so print it here. @@ -408,7 +434,7 @@ void DeclPrinter::VisitEnumDecl(EnumDecl *D) { } Out << *D; - if (D->isFixed()) + if (D->isFixed() && D->getASTContext().getLangOpts().CPlusPlus11) Out << " : " << D->getIntegerType().stream(Policy); if (D->isCompleteDefinition()) { @@ -449,6 +475,9 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { !D->isFunctionTemplateSpecialization()) prettyPrintPragmas(D); + if (D->isFunctionTemplateSpecialization()) + Out << "template<> "; + CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D); CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D); if (!Policy.SuppressSpecifiers) { @@ -473,6 +502,11 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { PrintingPolicy SubPolicy(Policy); SubPolicy.SuppressSpecifiers = false; std::string Proto = D->getNameInfo().getAsString(); + if (const TemplateArgumentList *TArgs = D->getTemplateSpecializationArgs()) { + llvm::raw_string_ostream POut(Proto); + DeclPrinter TArgPrinter(POut, SubPolicy, Indentation); + TArgPrinter.printTemplateArguments(*TArgs); + } QualType Ty = D->getType(); while (const ParenType *PT = dyn_cast<ParenType>(Ty)) { @@ -636,25 +670,29 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { Out << " = delete"; else if (D->isExplicitlyDefaulted()) Out << " = default"; - else if (D->doesThisDeclarationHaveABody() && !Policy.TerseOutput) { - if (!D->hasPrototype() && D->getNumParams()) { - // This is a K&R function definition, so we need to print the - // parameters. - Out << '\n'; - DeclPrinter ParamPrinter(Out, SubPolicy, Indentation); - Indentation += Policy.Indentation; - for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { - Indent(); - ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); - Out << ";\n"; - } - Indentation -= Policy.Indentation; - } else - Out << ' '; + else if (D->doesThisDeclarationHaveABody()) { + if (!Policy.TerseOutput) { + if (!D->hasPrototype() && D->getNumParams()) { + // This is a K&R function definition, so we need to print the + // parameters. + Out << '\n'; + DeclPrinter ParamPrinter(Out, SubPolicy, Indentation); + Indentation += Policy.Indentation; + for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { + Indent(); + ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); + Out << ";\n"; + } + Indentation -= Policy.Indentation; + } else + Out << ' '; - if (D->getBody()) - D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation); - Out << '\n'; + if (D->getBody()) + D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation); + } else { + if (isa<CXXConstructorDecl>(*D)) + Out << " {}"; + } } } @@ -662,7 +700,7 @@ void DeclPrinter::VisitFriendDecl(FriendDecl *D) { if (TypeSourceInfo *TSI = D->getFriendType()) { unsigned NumTPLists = D->getFriendTypeNumTemplateParameterLists(); for (unsigned i = 0; i < NumTPLists; ++i) - PrintTemplateParameters(D->getFriendTypeTemplateParameterList(i)); + printTemplateParameters(D->getFriendTypeTemplateParameterList(i)); Out << "friend "; Out << " " << TSI->getType().getAsString(Policy); } @@ -839,9 +877,15 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { prettyPrintAttributes(D); - if (D->getIdentifier()) + if (D->getIdentifier()) { Out << ' ' << *D; + if (auto S = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) + printTemplateArguments(S->getTemplateArgs(), S->getTemplateParameters()); + else if (auto S = dyn_cast<ClassTemplateSpecializationDecl>(D)) + printTemplateArguments(S->getTemplateArgs()); + } + if (D->isCompleteDefinition()) { // Print the base classes if (D->getNumBases()) { @@ -868,9 +912,13 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { // Print the class definition // FIXME: Doesn't print access specifiers, e.g., "public:" - Out << " {\n"; - VisitDeclContext(D); - Indent() << "}"; + if (Policy.TerseOutput) { + Out << " {}"; + } else { + Out << " {\n"; + VisitDeclContext(D); + Indent() << "}"; + } } } @@ -893,10 +941,8 @@ void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { Visit(*D->decls_begin()); } -void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params, - const TemplateArgumentList *Args) { +void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params) { assert(Params); - assert(!Args || Params->size() == Args->size()); Out << "template <"; @@ -905,8 +951,7 @@ void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params, Out << ", "; const Decl *Param = Params->getParam(i); - if (const TemplateTypeParmDecl *TTP = - dyn_cast<TemplateTypeParmDecl>(Param)) { + if (auto TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { if (TTP->wasDeclaredWithTypename()) Out << "typename "; @@ -918,30 +963,22 @@ void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params, Out << *TTP; - if (Args) { - Out << " = "; - Args->get(i).print(Policy, Out); - } else if (TTP->hasDefaultArgument()) { + if (TTP->hasDefaultArgument()) { Out << " = "; Out << TTP->getDefaultArgument().getAsString(Policy); }; - } else if (const NonTypeTemplateParmDecl *NTTP = - dyn_cast<NonTypeTemplateParmDecl>(Param)) { + } else if (auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) { StringRef Name; if (IdentifierInfo *II = NTTP->getIdentifier()) Name = II->getName(); printDeclType(NTTP->getType(), Name, NTTP->isParameterPack()); - if (Args) { - Out << " = "; - Args->get(i).print(Policy, Out); - } else if (NTTP->hasDefaultArgument()) { + if (NTTP->hasDefaultArgument()) { Out << " = "; NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy, Indentation); } - } else if (const TemplateTemplateParmDecl *TTPD = - dyn_cast<TemplateTemplateParmDecl>(Param)) { + } else if (auto TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) { VisitTemplateDecl(TTPD); // FIXME: print the default argument, if present. } @@ -950,8 +987,46 @@ void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params, Out << "> "; } +void DeclPrinter::printTemplateArguments(const TemplateArgumentList &Args, + const TemplateParameterList *Params) { + Out << "<"; + for (size_t I = 0, E = Args.size(); I < E; ++I) { + const TemplateArgument &A = Args[I]; + if (I) + Out << ", "; + if (Params) { + if (A.getKind() == TemplateArgument::Type) + if (auto T = A.getAsType()->getAs<TemplateTypeParmType>()) { + auto P = cast<TemplateTypeParmDecl>(Params->getParam(T->getIndex())); + Out << *P; + continue; + } + if (A.getKind() == TemplateArgument::Template) { + if (auto T = A.getAsTemplate().getAsTemplateDecl()) + if (auto TD = dyn_cast<TemplateTemplateParmDecl>(T)) { + auto P = cast<TemplateTemplateParmDecl>( + Params->getParam(TD->getIndex())); + Out << *P; + continue; + } + } + if (A.getKind() == TemplateArgument::Expression) { + if (auto E = dyn_cast<DeclRefExpr>(A.getAsExpr())) + if (auto N = dyn_cast<NonTypeTemplateParmDecl>(E->getDecl())) { + auto P = cast<NonTypeTemplateParmDecl>( + Params->getParam(N->getIndex())); + Out << *P; + continue; + } + } + } + A.print(Policy, Out); + } + Out << ">"; +} + void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) { - PrintTemplateParameters(D->getTemplateParameters()); + printTemplateParameters(D->getTemplateParameters()); if (const TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) { @@ -965,30 +1040,49 @@ void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) { } void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { + prettyPrintPragmas(D->getTemplatedDecl()); + VisitRedeclarableTemplateDecl(D); + if (PrintInstantiation) { - TemplateParameterList *Params = D->getTemplateParameters(); - for (auto *I : D->specializations()) { - prettyPrintPragmas(I); - PrintTemplateParameters(Params, I->getTemplateSpecializationArgs()); - Visit(I); - } + FunctionDecl *PrevDecl = D->getTemplatedDecl(); + const FunctionDecl *Def; + if (PrevDecl->isDefined(Def) && Def != PrevDecl) + return; + for (auto *I : D->specializations()) + if (I->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) { + if (!PrevDecl->isThisDeclarationADefinition()) + Out << ";\n"; + Indent(); + prettyPrintPragmas(I); + Visit(I); + } } - - prettyPrintPragmas(D->getTemplatedDecl()); - return VisitRedeclarableTemplateDecl(D); } void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) { + VisitRedeclarableTemplateDecl(D); + if (PrintInstantiation) { - TemplateParameterList *Params = D->getTemplateParameters(); - for (auto *I : D->specializations()) { - PrintTemplateParameters(Params, &I->getTemplateArgs()); - Visit(I); - Out << '\n'; - } + for (auto *I : D->specializations()) + if (I->getSpecializationKind() == TSK_ImplicitInstantiation) { + if (D->isThisDeclarationADefinition()) + Out << ";"; + Out << "\n"; + Visit(I); + } } +} + +void DeclPrinter::VisitClassTemplateSpecializationDecl( + ClassTemplateSpecializationDecl *D) { + Out << "template<> "; + VisitCXXRecordDecl(D); +} - return VisitRedeclarableTemplateDecl(D); +void DeclPrinter::VisitClassTemplatePartialSpecializationDecl( + ClassTemplatePartialSpecializationDecl *D) { + printTemplateParameters(D->getTemplateParameters()); + VisitCXXRecordDecl(D); } //---------------------------------------------------------------------------- @@ -1346,6 +1440,17 @@ void DeclPrinter::VisitUsingDecl(UsingDecl *D) { if (D->hasTypename()) Out << "typename "; D->getQualifier()->print(Out, Policy); + + // Use the correct record name when the using declaration is used for + // inheriting constructors. + for (const auto *Shadow : D->shadows()) { + if (const auto *ConstructorShadow = + dyn_cast<ConstructorUsingShadowDecl>(Shadow)) { + assert(Shadow->getDeclContext() == ConstructorShadow->getDeclContext()); + Out << *ConstructorShadow->getNominatedBaseClass(); + return; + } + } Out << *D; } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp index 37943cd..a5fbb0a 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp @@ -31,10 +31,11 @@ using namespace clang; TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef<NamedDecl *> Params, - SourceLocation RAngleLoc) + SourceLocation RAngleLoc, + Expr *RequiresClause) : TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc), - NumParams(Params.size()), ContainsUnexpandedParameterPack(false) { - assert(this->NumParams == NumParams && "Too many template parameters"); + NumParams(Params.size()), ContainsUnexpandedParameterPack(false), + HasRequiresClause(static_cast<bool>(RequiresClause)) { for (unsigned Idx = 0; Idx < NumParams; ++Idx) { NamedDecl *P = Params[Idx]; begin()[Idx] = P; @@ -52,15 +53,21 @@ TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc, // template parameter list does too. } } + if (RequiresClause) { + *getTrailingObjects<Expr *>() = RequiresClause; + } } -TemplateParameterList *TemplateParameterList::Create( - const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, - ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc) { - void *Mem = C.Allocate(totalSizeToAlloc<NamedDecl *>(Params.size()), - llvm::alignOf<TemplateParameterList>()); +TemplateParameterList * +TemplateParameterList::Create(const ASTContext &C, SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + ArrayRef<NamedDecl *> Params, + SourceLocation RAngleLoc, Expr *RequiresClause) { + void *Mem = C.Allocate(totalSizeToAlloc<NamedDecl *, Expr *>( + Params.size(), RequiresClause ? 1u : 0u), + alignof(TemplateParameterList)); return new (Mem) TemplateParameterList(TemplateLoc, LAngleLoc, Params, - RAngleLoc); + RAngleLoc, RequiresClause); } unsigned TemplateParameterList::getMinRequiredArguments() const { @@ -197,44 +204,6 @@ void RedeclarableTemplateDecl::addSpecializationImpl( SETraits::getDecl(Entry)); } -/// \brief Generate the injected template arguments for the given template -/// parameter list, e.g., for the injected-class-name of a class template. -static void GenerateInjectedTemplateArgs(ASTContext &Context, - TemplateParameterList *Params, - TemplateArgument *Args) { - for (NamedDecl *Param : *Params) { - TemplateArgument Arg; - if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { - QualType ArgType = Context.getTypeDeclType(TTP); - if (TTP->isParameterPack()) - ArgType = Context.getPackExpansionType(ArgType, None); - - Arg = TemplateArgument(ArgType); - } else if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) { - Expr *E = new (Context) DeclRefExpr(NTTP, /*enclosing*/ false, - NTTP->getType().getNonLValueExprType(Context), - Expr::getValueKindForType(NTTP->getType()), - NTTP->getLocation()); - - if (NTTP->isParameterPack()) - E = new (Context) PackExpansionExpr(Context.DependentTy, E, - NTTP->getLocation(), None); - Arg = TemplateArgument(E); - } else { - auto *TTP = cast<TemplateTemplateParmDecl>(Param); - if (TTP->isParameterPack()) - Arg = TemplateArgument(TemplateName(TTP), Optional<unsigned>()); - else - Arg = TemplateArgument(TemplateName(TTP)); - } - - if (Param->isTemplateParameterPack()) - Arg = TemplateArgument::CreatePackCopy(Context, Arg); - - *Args++ = Arg; - } -} - //===----------------------------------------------------------------------===// // FunctionTemplateDecl Implementation //===----------------------------------------------------------------------===// @@ -303,10 +272,13 @@ ArrayRef<TemplateArgument> FunctionTemplateDecl::getInjectedTemplateArgs() { TemplateParameterList *Params = getTemplateParameters(); Common *CommonPtr = getCommonPtr(); if (!CommonPtr->InjectedArgs) { - CommonPtr->InjectedArgs - = new (getASTContext()) TemplateArgument[Params->size()]; - GenerateInjectedTemplateArgs(getASTContext(), Params, - CommonPtr->InjectedArgs); + auto &Context = getASTContext(); + SmallVector<TemplateArgument, 16> TemplateArgs; + Context.getInjectedTemplateArgs(Params, TemplateArgs); + CommonPtr->InjectedArgs = + new (Context) TemplateArgument[TemplateArgs.size()]; + std::copy(TemplateArgs.begin(), TemplateArgs.end(), + CommonPtr->InjectedArgs); } return llvm::makeArrayRef(CommonPtr->InjectedArgs, Params->size()); @@ -325,12 +297,10 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, - NamedDecl *Decl, - ClassTemplateDecl *PrevDecl) { + NamedDecl *Decl) { AdoptTemplateParameterList(Params, cast<DeclContext>(Decl)); ClassTemplateDecl *New = new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl); - New->setPreviousDecl(PrevDecl); return New; } @@ -457,8 +427,7 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() { ASTContext &Context = getASTContext(); TemplateParameterList *Params = getTemplateParameters(); SmallVector<TemplateArgument, 16> TemplateArgs; - TemplateArgs.resize(Params->size()); - GenerateInjectedTemplateArgs(getASTContext(), Params, TemplateArgs.data()); + Context.getInjectedTemplateArgs(Params, TemplateArgs); CommonPtr->InjectedClassNameType = Context.getTemplateSpecializationType(TemplateName(this), TemplateArgs); @@ -754,9 +723,16 @@ void ClassTemplateSpecializationDecl::getNameForDiagnostic( raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const { NamedDecl::getNameForDiagnostic(OS, Policy, Qualified); - const TemplateArgumentList &TemplateArgs = getTemplateArgs(); - TemplateSpecializationType::PrintTemplateArgumentList( - OS, TemplateArgs.asArray(), Policy); + auto *PS = dyn_cast<ClassTemplatePartialSpecializationDecl>(this); + if (const ASTTemplateArgumentListInfo *ArgsAsWritten = + PS ? PS->getTemplateArgsAsWritten() : nullptr) { + TemplateSpecializationType::PrintTemplateArgumentList( + OS, ArgsAsWritten->arguments(), Policy); + } else { + const TemplateArgumentList &TemplateArgs = getTemplateArgs(); + TemplateSpecializationType::PrintTemplateArgumentList( + OS, TemplateArgs.asArray(), Policy); + } } ClassTemplateDecl * @@ -1086,9 +1062,16 @@ void VarTemplateSpecializationDecl::getNameForDiagnostic( raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const { NamedDecl::getNameForDiagnostic(OS, Policy, Qualified); - const TemplateArgumentList &TemplateArgs = getTemplateArgs(); - TemplateSpecializationType::PrintTemplateArgumentList( - OS, TemplateArgs.asArray(), Policy); + auto *PS = dyn_cast<VarTemplatePartialSpecializationDecl>(this); + if (const ASTTemplateArgumentListInfo *ArgsAsWritten = + PS ? PS->getTemplateArgsAsWritten() : nullptr) { + TemplateSpecializationType::PrintTemplateArgumentList( + OS, ArgsAsWritten->arguments(), Policy); + } else { + const TemplateArgumentList &TemplateArgs = getTemplateArgs(); + TemplateSpecializationType::PrintTemplateArgumentList( + OS, TemplateArgs.asArray(), Policy); + } } VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const { @@ -1169,7 +1152,7 @@ createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) { // <typename T, T ...Ints> NamedDecl *P[2] = {T, N}; auto *TPL = TemplateParameterList::Create( - C, SourceLocation(), SourceLocation(), P, SourceLocation()); + C, SourceLocation(), SourceLocation(), P, SourceLocation(), nullptr); // template <typename T, ...Ints> class IntSeq auto *TemplateTemplateParm = TemplateTemplateParmDecl::Create( @@ -1194,7 +1177,7 @@ createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) { // template <template <typename T, T ...Ints> class IntSeq, typename T, T N> return TemplateParameterList::Create(C, SourceLocation(), SourceLocation(), - Params, SourceLocation()); + Params, SourceLocation(), nullptr); } static TemplateParameterList * @@ -1215,7 +1198,7 @@ createTypePackElementParameterList(const ASTContext &C, DeclContext *DC) { NamedDecl *Params[] = {Index, Ts}; return TemplateParameterList::Create(C, SourceLocation(), SourceLocation(), llvm::makeArrayRef(Params), - SourceLocation()); + SourceLocation(), nullptr); } static TemplateParameterList *createBuiltinTemplateParameterList( diff --git a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp index 2a988e1..52791e5 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp @@ -11,14 +11,13 @@ // classes. // //===----------------------------------------------------------------------===// +#include "clang/AST/DeclarationName.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclarationName.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeOrdering.h" #include "clang/Basic/IdentifierTable.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -96,12 +95,18 @@ int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) { case DeclarationName::ObjCMultiArgSelector: { Selector LHSSelector = LHS.getObjCSelector(); Selector RHSSelector = RHS.getObjCSelector(); + // getNumArgs for ZeroArgSelector returns 0, but we still need to compare. + if (LHS.getNameKind() == DeclarationName::ObjCZeroArgSelector && + RHS.getNameKind() == DeclarationName::ObjCZeroArgSelector) { + return LHSSelector.getAsIdentifierInfo()->getName().compare( + RHSSelector.getAsIdentifierInfo()->getName()); + } unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs(); for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) { switch (LHSSelector.getNameForSlot(I).compare( RHSSelector.getNameForSlot(I))) { - case -1: return true; - case 1: return false; + case -1: return -1; + case 1: return 1; default: break; } } diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp index 091e878..14f31d0 100644 --- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" @@ -36,9 +35,33 @@ #include <cstring> using namespace clang; -const CXXRecordDecl *Expr::getBestDynamicClassType() const { - const Expr *E = ignoreParenBaseCasts(); +const Expr *Expr::getBestDynamicClassTypeExpr() const { + const Expr *E = this; + while (true) { + E = E->ignoreParenBaseCasts(); + + // Follow the RHS of a comma operator. + if (auto *BO = dyn_cast<BinaryOperator>(E)) { + if (BO->getOpcode() == BO_Comma) { + E = BO->getRHS(); + continue; + } + } + + // Step into initializer for materialized temporaries. + if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) { + E = MTE->GetTemporaryExpr(); + continue; + } + + break; + } + + return E; +} +const CXXRecordDecl *Expr::getBestDynamicClassType() const { + const Expr *E = getBestDynamicClassTypeExpr(); QualType DerivedType = E->getType(); if (const PointerType *PTy = DerivedType->getAs<PointerType>()) DerivedType = PTy->getPointeeType(); @@ -403,7 +426,7 @@ DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context, HasTemplateKWAndArgsInfo ? 1 : 0, TemplateArgs ? TemplateArgs->size() : 0); - void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>()); + void *Mem = Context.Allocate(Size, alignof(DeclRefExpr)); return new (Mem) DeclRefExpr(Context, QualifierLoc, TemplateKWLoc, D, RefersToEnclosingVariableOrCapture, NameInfo, FoundD, TemplateArgs, T, VK); @@ -420,7 +443,7 @@ DeclRefExpr *DeclRefExpr::CreateEmpty(const ASTContext &Context, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( HasQualifier ? 1 : 0, HasFoundDecl ? 1 : 0, HasTemplateKWAndArgsInfo, NumTemplateArgs); - void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>()); + void *Mem = Context.Allocate(Size, alignof(DeclRefExpr)); return new (Mem) DeclRefExpr(EmptyShell()); } @@ -495,20 +518,21 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { } return ""; } - if (auto *BD = dyn_cast<BlockDecl>(CurrentDecl)) { - std::unique_ptr<MangleContext> MC; - MC.reset(Context.createMangleContext()); - SmallString<256> Buffer; - llvm::raw_svector_ostream Out(Buffer); + if (isa<BlockDecl>(CurrentDecl)) { + // For blocks we only emit something if it is enclosed in a function + // For top-level block we'd like to include the name of variable, but we + // don't have it at this point. auto DC = CurrentDecl->getDeclContext(); if (DC->isFileContext()) - MC->mangleGlobalBlock(BD, /*ID*/ nullptr, Out); - else if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC)) - MC->mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, Out); - else if (const auto *DD = dyn_cast<CXXDestructorDecl>(DC)) - MC->mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, Out); - else - MC->mangleBlock(DC, BD, Out); + return ""; + + SmallString<256> Buffer; + llvm::raw_svector_ostream Out(Buffer); + if (auto *DCBlock = dyn_cast<BlockDecl>(DC)) + // For nested blocks, propagate up to the parent. + Out << ComputeName(IT, DCBlock); + else if (auto *DCDecl = dyn_cast<Decl>(DC)) + Out << ComputeName(IT, DCDecl) << "_block_invoke"; return Out.str(); } if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) { @@ -538,12 +562,13 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { FT = dyn_cast<FunctionProtoType>(AFT); if (IT == FuncSig) { - switch (FT->getCallConv()) { + switch (AFT->getCallConv()) { case CC_C: POut << "__cdecl "; break; case CC_X86StdCall: POut << "__stdcall "; break; case CC_X86FastCall: POut << "__fastcall "; break; case CC_X86ThisCall: POut << "__thiscall "; break; case CC_X86VectorCall: POut << "__vectorcall "; break; + case CC_X86RegCall: POut << "__regcall "; break; // Only bother printing the conventions that MSVC knows about. default: break; } @@ -561,12 +586,15 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { if (FT->isVariadic()) { if (FD->getNumParams()) POut << ", "; POut << "..."; + } else if ((IT == FuncSig || !Context.getLangOpts().CPlusPlus) && + !Decl->getNumParams()) { + POut << "void"; } } POut << ")"; if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { - const FunctionType *FT = MD->getType()->castAs<FunctionType>(); + assert(FT && "We must have a written prototype in this case."); if (FT->isConst()) POut << " const"; if (FT->isVolatile()) @@ -756,33 +784,33 @@ FloatingLiteral::Create(const ASTContext &C, EmptyShell Empty) { const llvm::fltSemantics &FloatingLiteral::getSemantics() const { switch(FloatingLiteralBits.Semantics) { case IEEEhalf: - return llvm::APFloat::IEEEhalf; + return llvm::APFloat::IEEEhalf(); case IEEEsingle: - return llvm::APFloat::IEEEsingle; + return llvm::APFloat::IEEEsingle(); case IEEEdouble: - return llvm::APFloat::IEEEdouble; + return llvm::APFloat::IEEEdouble(); case x87DoubleExtended: - return llvm::APFloat::x87DoubleExtended; + return llvm::APFloat::x87DoubleExtended(); case IEEEquad: - return llvm::APFloat::IEEEquad; + return llvm::APFloat::IEEEquad(); case PPCDoubleDouble: - return llvm::APFloat::PPCDoubleDouble; + return llvm::APFloat::PPCDoubleDouble(); } llvm_unreachable("Unrecognised floating semantics"); } void FloatingLiteral::setSemantics(const llvm::fltSemantics &Sem) { - if (&Sem == &llvm::APFloat::IEEEhalf) + if (&Sem == &llvm::APFloat::IEEEhalf()) FloatingLiteralBits.Semantics = IEEEhalf; - else if (&Sem == &llvm::APFloat::IEEEsingle) + else if (&Sem == &llvm::APFloat::IEEEsingle()) FloatingLiteralBits.Semantics = IEEEsingle; - else if (&Sem == &llvm::APFloat::IEEEdouble) + else if (&Sem == &llvm::APFloat::IEEEdouble()) FloatingLiteralBits.Semantics = IEEEdouble; - else if (&Sem == &llvm::APFloat::x87DoubleExtended) + else if (&Sem == &llvm::APFloat::x87DoubleExtended()) FloatingLiteralBits.Semantics = x87DoubleExtended; - else if (&Sem == &llvm::APFloat::IEEEquad) + else if (&Sem == &llvm::APFloat::IEEEquad()) FloatingLiteralBits.Semantics = IEEEquad; - else if (&Sem == &llvm::APFloat::PPCDoubleDouble) + else if (&Sem == &llvm::APFloat::PPCDoubleDouble()) FloatingLiteralBits.Semantics = PPCDoubleDouble; else llvm_unreachable("Unknown floating semantics"); @@ -794,7 +822,7 @@ void FloatingLiteral::setSemantics(const llvm::fltSemantics &Sem) { double FloatingLiteral::getValueAsApproximateDouble() const { llvm::APFloat V = getValue(); bool ignored; - V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven, + V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven, &ignored); return V.convertToDouble(); } @@ -832,9 +860,9 @@ StringLiteral *StringLiteral::Create(const ASTContext &C, StringRef Str, // Allocate enough space for the StringLiteral plus an array of locations for // any concatenated string tokens. - void *Mem = C.Allocate(sizeof(StringLiteral)+ - sizeof(SourceLocation)*(NumStrs-1), - llvm::alignOf<StringLiteral>()); + void *Mem = + C.Allocate(sizeof(StringLiteral) + sizeof(SourceLocation) * (NumStrs - 1), + alignof(StringLiteral)); StringLiteral *SL = new (Mem) StringLiteral(Ty); // OPTIMIZE: could allocate this appended to the StringLiteral. @@ -850,9 +878,9 @@ StringLiteral *StringLiteral::Create(const ASTContext &C, StringRef Str, StringLiteral *StringLiteral::CreateEmpty(const ASTContext &C, unsigned NumStrs) { - void *Mem = C.Allocate(sizeof(StringLiteral)+ - sizeof(SourceLocation)*(NumStrs-1), - llvm::alignOf<StringLiteral>()); + void *Mem = + C.Allocate(sizeof(StringLiteral) + sizeof(SourceLocation) * (NumStrs - 1), + alignof(StringLiteral)); StringLiteral *SL = new (Mem) StringLiteral(QualType()); SL->CharByteWidth = 0; SL->Length = 0; @@ -944,10 +972,13 @@ void StringLiteral::outputString(raw_ostream &OS) const { // Handle some common non-printable cases to make dumps prettier. case '\\': OS << "\\\\"; break; case '"': OS << "\\\""; break; - case '\n': OS << "\\n"; break; - case '\t': OS << "\\t"; break; case '\a': OS << "\\a"; break; case '\b': OS << "\\b"; break; + case '\f': OS << "\\f"; break; + case '\n': OS << "\\n"; break; + case '\r': OS << "\\r"; break; + case '\t': OS << "\\t"; break; + case '\v': OS << "\\v"; break; } } OS << '"'; @@ -1182,8 +1213,16 @@ void CallExpr::updateDependenciesFromArg(Expr *Arg) { ExprBits.ContainsUnexpandedParameterPack = true; } +FunctionDecl *CallExpr::getDirectCallee() { + return dyn_cast_or_null<FunctionDecl>(getCalleeDecl()); +} + Decl *CallExpr::getCalleeDecl() { - Expr *CEE = getCallee()->IgnoreParenImpCasts(); + return getCallee()->getReferencedDeclOfCallee(); +} + +Decl *Expr::getReferencedDeclOfCallee() { + Expr *CEE = IgnoreParenImpCasts(); while (SubstNonTypeTemplateParmExpr *NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(CEE)) { @@ -1206,10 +1245,6 @@ Decl *CallExpr::getCalleeDecl() { return nullptr; } -FunctionDecl *CallExpr::getDirectCallee() { - return dyn_cast_or_null<FunctionDecl>(getCalleeDecl()); -} - /// setNumArgs - This changes the number of arguments present in this call. /// Any orphaned expressions are deleted by this, and any new operands are set /// to null. @@ -1417,7 +1452,7 @@ MemberExpr *MemberExpr::Create( HasTemplateKWAndArgsInfo ? 1 : 0, targs ? targs->size() : 0); - void *Mem = C.Allocate(Size, llvm::alignOf<MemberExpr>()); + void *Mem = C.Allocate(Size, alignof(MemberExpr)); MemberExpr *E = new (Mem) MemberExpr(base, isarrow, OperatorLoc, memberdecl, nameinfo, ty, vk, ok); @@ -1570,6 +1605,8 @@ bool CastExpr::CastConsistency() const { case CK_ARCReclaimReturnedObject: case CK_ARCExtendBlockObject: case CK_ZeroToOCLEvent: + case CK_ZeroToOCLQueue: + case CK_IntToOCLSampler: assert(!getType()->isBooleanType() && "unheralded conversion to bool"); goto CheckNoBasePath; @@ -1830,6 +1867,24 @@ bool InitListExpr::isStringLiteralInit() const { return isa<StringLiteral>(Init) || isa<ObjCEncodeExpr>(Init); } +bool InitListExpr::isTransparent() const { + assert(isSemanticForm() && "syntactic form never semantically transparent"); + + // A glvalue InitListExpr is always just sugar. + if (isGLValue()) { + assert(getNumInits() == 1 && "multiple inits in glvalue init list"); + return true; + } + + // Otherwise, we're sugar if and only if we have exactly one initializer that + // is of the same type. + if (getNumInits() != 1 || !getInit(0)) + return false; + + return getType().getCanonicalType() == + getInit(0)->getType().getCanonicalType(); +} + SourceLocation InitListExpr::getLocStart() const { if (InitListExpr *SyntacticForm = getSyntacticForm()) return SyntacticForm->getLocStart(); @@ -2212,12 +2267,15 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, // effects (e.g. a placement new with an uninitialized POD). case CXXDeleteExprClass: return false; + case MaterializeTemporaryExprClass: + return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr() + ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); case CXXBindTemporaryExprClass: - return (cast<CXXBindTemporaryExpr>(this) - ->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx)); + return cast<CXXBindTemporaryExpr>(this)->getSubExpr() + ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); case ExprWithCleanupsClass: - return (cast<ExprWithCleanups>(this) - ->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx)); + return cast<ExprWithCleanups>(this)->getSubExpr() + ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); } } @@ -2748,7 +2806,8 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, CE->getCastKind() == CK_ToUnion || CE->getCastKind() == CK_ConstructorConversion || CE->getCastKind() == CK_NonAtomicToAtomic || - CE->getCastKind() == CK_AtomicToNonAtomic) + CE->getCastKind() == CK_AtomicToNonAtomic || + CE->getCastKind() == CK_IntToOCLSampler) return CE->getSubExpr()->isConstantInitializer(Ctx, false, Culprit); break; @@ -2843,6 +2902,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case UnaryExprOrTypeTraitExprClass: case AddrLabelExprClass: case GNUNullExprClass: + case ArrayInitIndexExprClass: case NoInitExprClass: case CXXBoolLiteralExprClass: case CXXNullPtrLiteralExprClass: @@ -2919,6 +2979,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case ExtVectorElementExprClass: case DesignatedInitExprClass: case DesignatedInitUpdateExprClass: + case ArrayInitLoopExprClass: case ParenListExprClass: case CXXPseudoDestructorExprClass: case CXXStdInitializerListExprClass: @@ -3307,11 +3368,16 @@ FieldDecl *Expr::getSourceBitField() { if (Ivar->isBitField()) return Ivar; - if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E)) + if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E)) { if (FieldDecl *Field = dyn_cast<FieldDecl>(DeclRef->getDecl())) if (Field->isBitField()) return Field; + if (BindingDecl *BD = dyn_cast<BindingDecl>(DeclRef->getDecl())) + if (Expr *E = BD->getBinding()) + return E->getSourceBitField(); + } + if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(E)) { if (BinOp->isAssignmentOp() && BinOp->getLHS()) return BinOp->getLHS()->getSourceBitField(); @@ -3328,6 +3394,7 @@ FieldDecl *Expr::getSourceBitField() { } bool Expr::refersToVectorElement() const { + // FIXME: Why do we not just look at the ObjectKind here? const Expr *E = this->IgnoreParens(); while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { @@ -3344,6 +3411,11 @@ bool Expr::refersToVectorElement() const { if (isa<ExtVectorElementExpr>(E)) return true; + if (auto *DRE = dyn_cast<DeclRefExpr>(E)) + if (auto *BD = dyn_cast<BindingDecl>(DRE->getDecl())) + if (auto *E = BD->getBinding()) + return E->refersToVectorElement(); + return false; } @@ -3396,8 +3468,11 @@ bool ExtVectorElementExpr::containsDuplicateElements() const { void ExtVectorElementExpr::getEncodedElementAccess( SmallVectorImpl<uint32_t> &Elts) const { StringRef Comp = Accessor->getName(); - if (Comp[0] == 's' || Comp[0] == 'S') + bool isNumericAccessor = false; + if (Comp[0] == 's' || Comp[0] == 'S') { Comp = Comp.substr(1); + isNumericAccessor = true; + } bool isHi = Comp == "hi"; bool isLo = Comp == "lo"; @@ -3416,7 +3491,7 @@ void ExtVectorElementExpr::getEncodedElementAccess( else if (isOdd) Index = 2 * i + 1; else - Index = ExtVectorType::getAccessorIdx(Comp[i]); + Index = ExtVectorType::getAccessorIdx(Comp[i], isNumericAccessor); Elts.push_back(Index); } @@ -3589,7 +3664,7 @@ DesignatedInitExpr::Create(const ASTContext &C, SourceLocation ColonOrEqualLoc, bool UsesColonSyntax, Expr *Init) { void *Mem = C.Allocate(totalSizeToAlloc<Stmt *>(IndexExprs.size() + 1), - llvm::alignOf<DesignatedInitExpr>()); + alignof(DesignatedInitExpr)); return new (Mem) DesignatedInitExpr(C, C.VoidTy, Designators, ColonOrEqualLoc, UsesColonSyntax, IndexExprs, Init); @@ -3598,7 +3673,7 @@ DesignatedInitExpr::Create(const ASTContext &C, DesignatedInitExpr *DesignatedInitExpr::CreateEmpty(const ASTContext &C, unsigned NumIndexExprs) { void *Mem = C.Allocate(totalSizeToAlloc<Stmt *>(NumIndexExprs + 1), - llvm::alignOf<DesignatedInitExpr>()); + alignof(DesignatedInitExpr)); return new (Mem) DesignatedInitExpr(NumIndexExprs + 1); } @@ -3738,7 +3813,7 @@ PseudoObjectExpr *PseudoObjectExpr::Create(const ASTContext &Context, unsigned numSemanticExprs) { void *buffer = Context.Allocate(totalSizeToAlloc<Expr *>(1 + numSemanticExprs), - llvm::alignOf<PseudoObjectExpr>()); + alignof(PseudoObjectExpr)); return new(buffer) PseudoObjectExpr(sh, numSemanticExprs); } @@ -3766,7 +3841,7 @@ PseudoObjectExpr *PseudoObjectExpr::Create(const ASTContext &C, Expr *syntax, } void *buffer = C.Allocate(totalSizeToAlloc<Expr *>(semantics.size() + 1), - llvm::alignOf<PseudoObjectExpr>()); + alignof(PseudoObjectExpr)); return new(buffer) PseudoObjectExpr(type, VK, syntax, semantics, resultIndex); } diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp index a13033d..ad510e0 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp @@ -25,6 +25,22 @@ using namespace clang; // Child Iterators for iterating over subexpressions/substatements //===----------------------------------------------------------------------===// +bool CXXOperatorCallExpr::isInfixBinaryOp() const { + // An infix binary operator is any operator with two arguments other than + // operator() and operator[]. Note that none of these operators can have + // default arguments, so it suffices to check the number of argument + // expressions. + if (getNumArgs() != 2) + return false; + + switch (getOperator()) { + case OO_Call: case OO_Subscript: + return false; + default: + return true; + } +} + bool CXXTypeidExpr::isPotentiallyEvaluated() const { if (isTypeOperand()) return false; @@ -62,7 +78,7 @@ SourceLocation CXXScalarValueInitExpr::getLocStart() const { // CXXNewExpr CXXNewExpr::CXXNewExpr(const ASTContext &C, bool globalNew, FunctionDecl *operatorNew, FunctionDecl *operatorDelete, - bool usualArrayDeleteWantsSize, + bool PassAlignment, bool usualArrayDeleteWantsSize, ArrayRef<Expr*> placementArgs, SourceRange typeIdParens, Expr *arraySize, InitializationStyle initializationStyle, @@ -76,7 +92,8 @@ CXXNewExpr::CXXNewExpr(const ASTContext &C, bool globalNew, SubExprs(nullptr), OperatorNew(operatorNew), OperatorDelete(operatorDelete), AllocatedTypeInfo(allocatedTypeInfo), TypeIdParens(typeIdParens), Range(Range), DirectInitRange(directInitRange), - GlobalNew(globalNew), UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) { + GlobalNew(globalNew), PassAlignment(PassAlignment), + UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) { assert((initializer != nullptr || initializationStyle == NoInit) && "Only NoInit can have no initializer."); StoredInitializationStyle = initializer ? initializationStyle + 1 : 0; @@ -226,7 +243,7 @@ UnresolvedLookupExpr::Create(const ASTContext &C, std::size_t Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(1, num_args); - void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedLookupExpr>()); + void *Mem = C.Allocate(Size, alignof(UnresolvedLookupExpr)); return new (Mem) UnresolvedLookupExpr(C, NamingClass, QualifierLoc, TemplateKWLoc, NameInfo, ADL, /*Overload*/ true, Args, @@ -241,7 +258,7 @@ UnresolvedLookupExpr::CreateEmpty(const ASTContext &C, std::size_t Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( HasTemplateKWAndArgsInfo, NumTemplateArgs); - void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedLookupExpr>()); + void *Mem = C.Allocate(Size, alignof(UnresolvedLookupExpr)); UnresolvedLookupExpr *E = new (Mem) UnresolvedLookupExpr(EmptyShell()); E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo; return E; @@ -284,9 +301,8 @@ OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C, } } - Results = static_cast<DeclAccessPair *>( - C.Allocate(sizeof(DeclAccessPair) * NumResults, - llvm::alignOf<DeclAccessPair>())); + Results = static_cast<DeclAccessPair *>(C.Allocate( + sizeof(DeclAccessPair) * NumResults, alignof(DeclAccessPair))); memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair)); } @@ -323,11 +339,11 @@ void OverloadExpr::initializeResults(const ASTContext &C, assert(!Results && "Results already initialized!"); NumResults = End - Begin; if (NumResults) { - Results = static_cast<DeclAccessPair *>( - C.Allocate(sizeof(DeclAccessPair) * NumResults, - - llvm::alignOf<DeclAccessPair>())); - memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair)); + Results = static_cast<DeclAccessPair *>( + C.Allocate(sizeof(DeclAccessPair) * NumResults, + + alignof(DeclAccessPair))); + memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair)); } } @@ -853,8 +869,6 @@ LambdaExpr::LambdaExpr(QualType T, SourceRange IntroducerRange, SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures, bool ExplicitParams, bool ExplicitResultType, ArrayRef<Expr *> CaptureInits, - ArrayRef<VarDecl *> ArrayIndexVars, - ArrayRef<unsigned> ArrayIndexStarts, SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack) : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary, T->isDependentType(), @@ -891,17 +905,6 @@ LambdaExpr::LambdaExpr(QualType T, SourceRange IntroducerRange, // Copy the body of the lambda. *Stored++ = getCallOperator()->getBody(); - - // Copy the array index variables, if any. - HasArrayIndexVars = !ArrayIndexVars.empty(); - if (HasArrayIndexVars) { - assert(ArrayIndexStarts.size() == NumCaptures); - memcpy(getArrayIndexVars(), ArrayIndexVars.data(), - sizeof(VarDecl *) * ArrayIndexVars.size()); - memcpy(getArrayIndexStarts(), ArrayIndexStarts.data(), - sizeof(unsigned) * Captures.size()); - getArrayIndexStarts()[Captures.size()] = ArrayIndexVars.size(); - } } LambdaExpr *LambdaExpr::Create( @@ -909,31 +912,24 @@ LambdaExpr *LambdaExpr::Create( SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures, bool ExplicitParams, bool ExplicitResultType, ArrayRef<Expr *> CaptureInits, - ArrayRef<VarDecl *> ArrayIndexVars, ArrayRef<unsigned> ArrayIndexStarts, SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack) { // Determine the type of the expression (i.e., the type of the // function object we're creating). QualType T = Context.getTypeDeclType(Class); - unsigned Size = totalSizeToAlloc<Stmt *, unsigned, VarDecl *>( - Captures.size() + 1, ArrayIndexVars.empty() ? 0 : Captures.size() + 1, - ArrayIndexVars.size()); + unsigned Size = totalSizeToAlloc<Stmt *>(Captures.size() + 1); void *Mem = Context.Allocate(Size); - return new (Mem) LambdaExpr(T, IntroducerRange, - CaptureDefault, CaptureDefaultLoc, Captures, - ExplicitParams, ExplicitResultType, - CaptureInits, ArrayIndexVars, ArrayIndexStarts, - ClosingBrace, ContainsUnexpandedParameterPack); + return new (Mem) + LambdaExpr(T, IntroducerRange, CaptureDefault, CaptureDefaultLoc, + Captures, ExplicitParams, ExplicitResultType, CaptureInits, + ClosingBrace, ContainsUnexpandedParameterPack); } LambdaExpr *LambdaExpr::CreateDeserialized(const ASTContext &C, - unsigned NumCaptures, - unsigned NumArrayIndexVars) { - unsigned Size = totalSizeToAlloc<Stmt *, unsigned, VarDecl *>( - NumCaptures + 1, NumArrayIndexVars ? NumCaptures + 1 : 0, - NumArrayIndexVars); + unsigned NumCaptures) { + unsigned Size = totalSizeToAlloc<Stmt *>(NumCaptures + 1); void *Mem = C.Allocate(Size); - return new (Mem) LambdaExpr(EmptyShell(), NumCaptures, NumArrayIndexVars > 0); + return new (Mem) LambdaExpr(EmptyShell(), NumCaptures); } bool LambdaExpr::isInitCapture(const LambdaCapture *C) const { @@ -979,19 +975,6 @@ LambdaExpr::capture_range LambdaExpr::implicit_captures() const { return capture_range(implicit_capture_begin(), implicit_capture_end()); } -ArrayRef<VarDecl *> -LambdaExpr::getCaptureInitIndexVars(const_capture_init_iterator Iter) const { - assert(HasArrayIndexVars && "No array index-var data?"); - - unsigned Index = Iter - capture_init_begin(); - assert(Index < getLambdaClass()->getLambdaData().NumCaptures && - "Capture index out-of-range"); - VarDecl *const *IndexVars = getArrayIndexVars(); - const unsigned *IndexStarts = getArrayIndexStarts(); - return llvm::makeArrayRef(IndexVars + IndexStarts[Index], - IndexVars + IndexStarts[Index + 1]); -} - CXXRecordDecl *LambdaExpr::getLambdaClass() const { return getType()->getAsCXXRecordDecl(); } @@ -1041,7 +1024,7 @@ ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, Expr *subexpr, bool CleanupsHaveSideEffects, ArrayRef<CleanupObject> objects) { void *buffer = C.Allocate(totalSizeToAlloc<CleanupObject>(objects.size()), - llvm::alignOf<ExprWithCleanups>()); + alignof(ExprWithCleanups)); return new (buffer) ExprWithCleanups(subexpr, CleanupsHaveSideEffects, objects); } @@ -1055,7 +1038,7 @@ ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, EmptyShell empty, unsigned numObjects) { void *buffer = C.Allocate(totalSizeToAlloc<CleanupObject>(numObjects), - llvm::alignOf<ExprWithCleanups>()); + alignof(ExprWithCleanups)); return new (buffer) ExprWithCleanups(empty, numObjects); } @@ -1154,7 +1137,7 @@ CXXDependentScopeMemberExpr::Create(const ASTContext &C, totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( HasTemplateKWAndArgsInfo, NumTemplateArgs); - void *Mem = C.Allocate(Size, llvm::alignOf<CXXDependentScopeMemberExpr>()); + void *Mem = C.Allocate(Size, alignof(CXXDependentScopeMemberExpr)); return new (Mem) CXXDependentScopeMemberExpr(C, Base, BaseType, IsArrow, OperatorLoc, QualifierLoc, @@ -1171,7 +1154,7 @@ CXXDependentScopeMemberExpr::CreateEmpty(const ASTContext &C, std::size_t Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( HasTemplateKWAndArgsInfo, NumTemplateArgs); - void *Mem = C.Allocate(Size, llvm::alignOf<CXXDependentScopeMemberExpr>()); + void *Mem = C.Allocate(Size, alignof(CXXDependentScopeMemberExpr)); CXXDependentScopeMemberExpr *E = new (Mem) CXXDependentScopeMemberExpr(C, nullptr, QualType(), 0, SourceLocation(), @@ -1255,7 +1238,7 @@ UnresolvedMemberExpr *UnresolvedMemberExpr::Create( totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( HasTemplateKWAndArgsInfo, TemplateArgs ? TemplateArgs->size() : 0); - void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedMemberExpr>()); + void *Mem = C.Allocate(Size, alignof(UnresolvedMemberExpr)); return new (Mem) UnresolvedMemberExpr( C, HasUnresolvedUsing, Base, BaseType, IsArrow, OperatorLoc, QualifierLoc, TemplateKWLoc, MemberNameInfo, TemplateArgs, Begin, End); @@ -1270,7 +1253,7 @@ UnresolvedMemberExpr::CreateEmpty(const ASTContext &C, totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( HasTemplateKWAndArgsInfo, NumTemplateArgs); - void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedMemberExpr>()); + void *Mem = C.Allocate(Size, alignof(UnresolvedMemberExpr)); UnresolvedMemberExpr *E = new (Mem) UnresolvedMemberExpr(EmptyShell()); E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo; return E; diff --git a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp index 89cc9bc..adb74b8 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp @@ -141,10 +141,9 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { return Cl::CL_LValue; // C99 6.5.2.5p5 says that compound literals are lvalues. - // In C++, they're prvalue temporaries. + // In C++, they're prvalue temporaries, except for file-scope arrays. case Expr::CompoundLiteralExprClass: - return Ctx.getLangOpts().CPlusPlus ? ClassifyTemporary(E->getType()) - : Cl::CL_LValue; + return !E->isLValue() ? ClassifyTemporary(E->getType()) : Cl::CL_LValue; // Expressions that are prvalues. case Expr::CXXBoolLiteralExprClass: @@ -186,6 +185,8 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::ObjCIndirectCopyRestoreExprClass: case Expr::AtomicExprClass: case Expr::CXXFoldExprClass: + case Expr::ArrayInitLoopExprClass: + case Expr::ArrayInitIndexExprClass: case Expr::NoInitExprClass: case Expr::DesignatedInitUpdateExprClass: case Expr::CoyieldExprClass: @@ -196,11 +197,20 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { return ClassifyInternal(Ctx, cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement()); - // C++ [expr.sub]p1: The result is an lvalue of type "T". - // However, subscripting vector types is more like member access. + // C, C++98 [expr.sub]p1: The result is an lvalue of type "T". + // C++11 (DR1213): in the case of an array operand, the result is an lvalue + // if that operand is an lvalue and an xvalue otherwise. + // Subscripting vector types is more like member access. case Expr::ArraySubscriptExprClass: if (cast<ArraySubscriptExpr>(E)->getBase()->getType()->isVectorType()) return ClassifyInternal(Ctx, cast<ArraySubscriptExpr>(E)->getBase()); + if (Lang.CPlusPlus11) { + // Step over the array-to-pointer decay if present, but not over the + // temporary materialization. + auto *Base = cast<ArraySubscriptExpr>(E)->getBase()->IgnoreImpCasts(); + if (Base->getType()->isArrayType()) + return ClassifyInternal(Ctx, Base); + } return Cl::CL_LValue; // C++ [expr.prim.general]p3: The result is an lvalue if the entity is a @@ -429,6 +439,7 @@ static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) { else islvalue = isa<VarDecl>(D) || isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || + isa<BindingDecl>(D) || (Ctx.getLangOpts().CPlusPlus && (isa<FunctionDecl>(D) || isa<MSPropertyDecl>(D) || isa<FunctionTemplateDecl>(D))); diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp index df944e8..2c0fce9 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp @@ -36,6 +36,7 @@ #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/CharUnits.h" #include "clang/AST/Expr.h" #include "clang/AST/RecordLayout.h" @@ -43,7 +44,6 @@ #include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" #include <cstring> #include <functional> @@ -76,8 +76,8 @@ namespace { const Expr *Inner = Temp->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); // Keep any cv-qualifiers from the reference if we generated a temporary - // for it. - if (Inner != Temp) + // for it directly. Otherwise use the type after adjustment. + if (!Adjustments.empty()) return Inner->getType(); } @@ -109,19 +109,57 @@ namespace { return getAsBaseOrMember(E).getInt(); } + /// Given a CallExpr, try to get the alloc_size attribute. May return null. + static const AllocSizeAttr *getAllocSizeAttr(const CallExpr *CE) { + const FunctionDecl *Callee = CE->getDirectCallee(); + return Callee ? Callee->getAttr<AllocSizeAttr>() : nullptr; + } + + /// Attempts to unwrap a CallExpr (with an alloc_size attribute) from an Expr. + /// This will look through a single cast. + /// + /// Returns null if we couldn't unwrap a function with alloc_size. + static const CallExpr *tryUnwrapAllocSizeCall(const Expr *E) { + if (!E->getType()->isPointerType()) + return nullptr; + + E = E->IgnoreParens(); + // If we're doing a variable assignment from e.g. malloc(N), there will + // probably be a cast of some kind. Ignore it. + if (const auto *Cast = dyn_cast<CastExpr>(E)) + E = Cast->getSubExpr()->IgnoreParens(); + + if (const auto *CE = dyn_cast<CallExpr>(E)) + return getAllocSizeAttr(CE) ? CE : nullptr; + return nullptr; + } + + /// Determines whether or not the given Base contains a call to a function + /// with the alloc_size attribute. + static bool isBaseAnAllocSizeCall(APValue::LValueBase Base) { + const auto *E = Base.dyn_cast<const Expr *>(); + return E && E->getType()->isPointerType() && tryUnwrapAllocSizeCall(E); + } + + /// Determines if an LValue with the given LValueBase will have an unsized + /// array in its designator. /// Find the path length and type of the most-derived subobject in the given /// path, and find the size of the containing array, if any. - static - unsigned findMostDerivedSubobject(ASTContext &Ctx, QualType Base, - ArrayRef<APValue::LValuePathEntry> Path, - uint64_t &ArraySize, QualType &Type, - bool &IsArray) { + static unsigned + findMostDerivedSubobject(ASTContext &Ctx, APValue::LValueBase Base, + ArrayRef<APValue::LValuePathEntry> Path, + uint64_t &ArraySize, QualType &Type, bool &IsArray) { + // This only accepts LValueBases from APValues, and APValues don't support + // arrays that lack size info. + assert(!isBaseAnAllocSizeCall(Base) && + "Unsized arrays shouldn't appear here"); unsigned MostDerivedLength = 0; - Type = Base; + Type = getType(Base); + for (unsigned I = 0, N = Path.size(); I != N; ++I) { if (Type->isArrayType()) { const ConstantArrayType *CAT = - cast<ConstantArrayType>(Ctx.getAsArrayType(Type)); + cast<ConstantArrayType>(Ctx.getAsArrayType(Type)); Type = CAT->getElementType(); ArraySize = CAT->getSize().getZExtValue(); MostDerivedLength = I + 1; @@ -162,17 +200,23 @@ namespace { /// Is this a pointer one past the end of an object? unsigned IsOnePastTheEnd : 1; + /// Indicator of whether the first entry is an unsized array. + unsigned FirstEntryIsAnUnsizedArray : 1; + /// Indicator of whether the most-derived object is an array element. unsigned MostDerivedIsArrayElement : 1; /// The length of the path to the most-derived object of which this is a /// subobject. - unsigned MostDerivedPathLength : 29; + unsigned MostDerivedPathLength : 28; /// The size of the array of which the most-derived object is an element. /// This will always be 0 if the most-derived object is not an array /// element. 0 is not an indicator of whether or not the most-derived object /// is an array, however, because 0-length arrays are allowed. + /// + /// If the current array is an unsized array, the value of this is + /// undefined. uint64_t MostDerivedArraySize; /// The type of the most derived object referred to by this address. @@ -187,23 +231,24 @@ namespace { explicit SubobjectDesignator(QualType T) : Invalid(false), IsOnePastTheEnd(false), - MostDerivedIsArrayElement(false), MostDerivedPathLength(0), - MostDerivedArraySize(0), MostDerivedType(T) {} + FirstEntryIsAnUnsizedArray(false), MostDerivedIsArrayElement(false), + MostDerivedPathLength(0), MostDerivedArraySize(0), + MostDerivedType(T) {} SubobjectDesignator(ASTContext &Ctx, const APValue &V) : Invalid(!V.isLValue() || !V.hasLValuePath()), IsOnePastTheEnd(false), - MostDerivedIsArrayElement(false), MostDerivedPathLength(0), - MostDerivedArraySize(0) { + FirstEntryIsAnUnsizedArray(false), MostDerivedIsArrayElement(false), + MostDerivedPathLength(0), MostDerivedArraySize(0) { + assert(V.isLValue() && "Non-LValue used to make an LValue designator?"); if (!Invalid) { IsOnePastTheEnd = V.isLValueOnePastTheEnd(); ArrayRef<PathEntry> VEntries = V.getLValuePath(); Entries.insert(Entries.end(), VEntries.begin(), VEntries.end()); if (V.getLValueBase()) { bool IsArray = false; - MostDerivedPathLength = - findMostDerivedSubobject(Ctx, getType(V.getLValueBase()), - V.getLValuePath(), MostDerivedArraySize, - MostDerivedType, IsArray); + MostDerivedPathLength = findMostDerivedSubobject( + Ctx, V.getLValueBase(), V.getLValuePath(), MostDerivedArraySize, + MostDerivedType, IsArray); MostDerivedIsArrayElement = IsArray; } } @@ -214,12 +259,26 @@ namespace { Entries.clear(); } + /// Determine whether the most derived subobject is an array without a + /// known bound. + bool isMostDerivedAnUnsizedArray() const { + assert(!Invalid && "Calling this makes no sense on invalid designators"); + return Entries.size() == 1 && FirstEntryIsAnUnsizedArray; + } + + /// Determine what the most derived array's size is. Results in an assertion + /// failure if the most derived array lacks a size. + uint64_t getMostDerivedArraySize() const { + assert(!isMostDerivedAnUnsizedArray() && "Unsized array has no size"); + return MostDerivedArraySize; + } + /// Determine whether this is a one-past-the-end pointer. bool isOnePastTheEnd() const { assert(!Invalid); if (IsOnePastTheEnd) return true; - if (MostDerivedIsArrayElement && + if (!isMostDerivedAnUnsizedArray() && MostDerivedIsArrayElement && Entries[MostDerivedPathLength - 1].ArrayIndex == MostDerivedArraySize) return true; return false; @@ -247,6 +306,21 @@ namespace { MostDerivedArraySize = CAT->getSize().getZExtValue(); MostDerivedPathLength = Entries.size(); } + /// Update this designator to refer to the first element within the array of + /// elements of type T. This is an array of unknown size. + void addUnsizedArrayUnchecked(QualType ElemTy) { + PathEntry Entry; + Entry.ArrayIndex = 0; + Entries.push_back(Entry); + + MostDerivedType = ElemTy; + MostDerivedIsArrayElement = true; + // The value in MostDerivedArraySize is undefined in this case. So, set it + // to an arbitrary value that's likely to loudly break things if it's + // used. + MostDerivedArraySize = std::numeric_limits<uint64_t>::max() / 2; + MostDerivedPathLength = Entries.size(); + } /// Update this designator to refer to the given base or member of this /// object. void addDeclUnchecked(const Decl *D, bool Virtual = false) { @@ -280,10 +354,16 @@ namespace { /// Add N to the address of this subobject. void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) { if (Invalid) return; + if (isMostDerivedAnUnsizedArray()) { + // Can't verify -- trust that the user is doing the right thing (or if + // not, trust that the caller will catch the bad behavior). + Entries.back().ArrayIndex += N; + return; + } if (MostDerivedPathLength == Entries.size() && MostDerivedIsArrayElement) { Entries.back().ArrayIndex += N; - if (Entries.back().ArrayIndex > MostDerivedArraySize) { + if (Entries.back().ArrayIndex > getMostDerivedArraySize()) { diagnosePointerArithmetic(Info, E, Entries.back().ArrayIndex); setInvalid(); } @@ -310,15 +390,9 @@ namespace { /// Parent - The caller of this stack frame. CallStackFrame *Caller; - /// CallLoc - The location of the call expression for this call. - SourceLocation CallLoc; - /// Callee - The function which was called. const FunctionDecl *Callee; - /// Index - The call index of this call. - unsigned Index; - /// This - The binding for the this pointer in this call, if any. const LValue *This; @@ -333,6 +407,12 @@ namespace { /// Temporaries - Temporary lvalues materialized within this stack frame. MapTy Temporaries; + /// CallLoc - The location of the call expression for this call. + SourceLocation CallLoc; + + /// Index - The call index of this call. + unsigned Index; + CallStackFrame(EvalInfo &Info, SourceLocation CallLoc, const FunctionDecl *Callee, const LValue *This, APValue *Arguments); @@ -433,7 +513,7 @@ namespace { /// rules. For example, the RHS of (0 && foo()) is not evaluated. We can /// evaluate the expression regardless of what the RHS is, but C only allows /// certain things in certain situations. - struct EvalInfo { + struct LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) EvalInfo { ASTContext &Ctx; /// EvalStatus - Contains information about the evaluation. @@ -469,6 +549,10 @@ namespace { /// declaration whose initializer is being evaluated, if any. APValue *EvaluatingDeclValue; + /// The current array initialization index, if we're performing array + /// initialization. + uint64_t ArrayInitIndex = -1; + /// HasActiveDiagnostic - Was the previous diagnostic stored? If so, further /// notes attached to it will also be stored, otherwise they will not be. bool HasActiveDiagnostic; @@ -520,9 +604,17 @@ namespace { /// gets a chance to look at it. EM_PotentialConstantExpressionUnevaluated, - /// Evaluate as a constant expression. Continue evaluating if we find a - /// MemberExpr with a base that can't be evaluated. - EM_DesignatorFold, + /// Evaluate as a constant expression. In certain scenarios, if: + /// - we find a MemberExpr with a base that can't be evaluated, or + /// - we find a variable initialized with a call to a function that has + /// the alloc_size attribute on it + /// then we may consider evaluation to have succeeded. + /// + /// In either case, the LValue returned shall have an invalid base; in the + /// former, the base will be the invalid MemberExpr, in the latter, the + /// base will be either the alloc_size CallExpr or a CastExpr wrapping + /// said CallExpr. + EM_OffsetFold, } EvalMode; /// Are we checking whether the expression is a potential constant @@ -624,7 +716,7 @@ namespace { case EM_PotentialConstantExpression: case EM_ConstantExpressionUnevaluated: case EM_PotentialConstantExpressionUnevaluated: - case EM_DesignatorFold: + case EM_OffsetFold: HasActiveDiagnostic = false; return OptionalDiagnostic(); } @@ -716,7 +808,7 @@ namespace { case EM_ConstantExpression: case EM_ConstantExpressionUnevaluated: case EM_ConstantFold: - case EM_DesignatorFold: + case EM_OffsetFold: return false; } llvm_unreachable("Missed EvalMode case"); @@ -735,7 +827,7 @@ namespace { case EM_EvaluateForOverflow: case EM_IgnoreSideEffects: case EM_ConstantFold: - case EM_DesignatorFold: + case EM_OffsetFold: return true; case EM_PotentialConstantExpression: @@ -771,7 +863,7 @@ namespace { case EM_ConstantExpressionUnevaluated: case EM_ConstantFold: case EM_IgnoreSideEffects: - case EM_DesignatorFold: + case EM_OffsetFold: return false; } llvm_unreachable("Missed EvalMode case"); @@ -787,7 +879,7 @@ namespace { /// (Foo(), 1) // use noteSideEffect /// (Foo() || true) // use noteSideEffect /// Foo() + 1 // use noteFailure - LLVM_ATTRIBUTE_UNUSED_RESULT bool noteFailure() { + LLVM_NODISCARD bool noteFailure() { // Failure when evaluating some expression often means there is some // subexpression whose evaluation was skipped. Therefore, (because we // don't track whether we skipped an expression when unwinding after an @@ -800,9 +892,19 @@ namespace { return KeepGoing; } - bool allowInvalidBaseExpr() const { - return EvalMode == EM_DesignatorFold; - } + class ArrayInitLoopIndex { + EvalInfo &Info; + uint64_t OuterIndex; + + public: + ArrayInitLoopIndex(EvalInfo &Info) + : Info(Info), OuterIndex(Info.ArrayInitIndex) { + Info.ArrayInitIndex = 0; + } + ~ArrayInitLoopIndex() { Info.ArrayInitIndex = OuterIndex; } + + operator uint64_t&() { return Info.ArrayInitIndex; } + }; }; /// Object used to treat all foldable expressions as constant expressions. @@ -838,11 +940,10 @@ namespace { struct FoldOffsetRAII { EvalInfo &Info; EvalInfo::EvaluationMode OldMode; - explicit FoldOffsetRAII(EvalInfo &Info, bool Subobject) + explicit FoldOffsetRAII(EvalInfo &Info) : Info(Info), OldMode(Info.EvalMode) { if (!Info.checkingPotentialConstantExpression()) - Info.EvalMode = Subobject ? EvalInfo::EM_DesignatorFold - : EvalInfo::EM_ConstantFold; + Info.EvalMode = EvalInfo::EM_OffsetFold; } ~FoldOffsetRAII() { Info.EvalMode = OldMode; } @@ -948,10 +1049,12 @@ bool SubobjectDesignator::checkSubobject(EvalInfo &Info, const Expr *E, void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info, const Expr *E, uint64_t N) { + // If we're complaining, we must be able to statically determine the size of + // the most derived array. if (MostDerivedPathLength == Entries.size() && MostDerivedIsArrayElement) Info.CCEDiag(E, diag::note_constexpr_array_index) << static_cast<int>(N) << /*array*/ 0 - << static_cast<unsigned>(MostDerivedArraySize); + << static_cast<unsigned>(getMostDerivedArraySize()); else Info.CCEDiag(E, diag::note_constexpr_array_index) << static_cast<int>(N) << /*non-array*/ 1; @@ -961,8 +1064,8 @@ void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info, CallStackFrame::CallStackFrame(EvalInfo &Info, SourceLocation CallLoc, const FunctionDecl *Callee, const LValue *This, APValue *Arguments) - : Info(Info), Caller(Info.CurrentCall), CallLoc(CallLoc), Callee(Callee), - Index(Info.NextCallIndex++), This(This), Arguments(Arguments) { + : Info(Info), Caller(Info.CurrentCall), Callee(Callee), This(This), + Arguments(Arguments), CallLoc(CallLoc), Index(Info.NextCallIndex++) { Info.CurrentCall = this; ++Info.CallStackDepth; } @@ -1032,7 +1135,7 @@ namespace { APSInt IntReal, IntImag; APFloat FloatReal, FloatImag; - ComplexValue() : FloatReal(APFloat::Bogus), FloatImag(APFloat::Bogus) {} + ComplexValue() : FloatReal(APFloat::Bogus()), FloatImag(APFloat::Bogus()) {} void makeComplexFloat() { IsInt = false; } bool isComplexFloat() const { return !IsInt; } @@ -1070,6 +1173,7 @@ namespace { unsigned InvalidBase : 1; unsigned CallIndex : 31; SubobjectDesignator Designator; + bool IsNullPtr; const APValue::LValueBase getLValueBase() const { return Base; } CharUnits &getLValueOffset() { return Offset; } @@ -1077,29 +1181,47 @@ namespace { unsigned getLValueCallIndex() const { return CallIndex; } SubobjectDesignator &getLValueDesignator() { return Designator; } const SubobjectDesignator &getLValueDesignator() const { return Designator;} + bool isNullPointer() const { return IsNullPtr;} void moveInto(APValue &V) const { if (Designator.Invalid) - V = APValue(Base, Offset, APValue::NoLValuePath(), CallIndex); - else + V = APValue(Base, Offset, APValue::NoLValuePath(), CallIndex, + IsNullPtr); + else { + assert(!InvalidBase && "APValues can't handle invalid LValue bases"); + assert(!Designator.FirstEntryIsAnUnsizedArray && + "Unsized array with a valid base?"); V = APValue(Base, Offset, Designator.Entries, - Designator.IsOnePastTheEnd, CallIndex); + Designator.IsOnePastTheEnd, CallIndex, IsNullPtr); + } } void setFrom(ASTContext &Ctx, const APValue &V) { - assert(V.isLValue()); + assert(V.isLValue() && "Setting LValue from a non-LValue?"); Base = V.getLValueBase(); Offset = V.getLValueOffset(); InvalidBase = false; CallIndex = V.getLValueCallIndex(); Designator = SubobjectDesignator(Ctx, V); + IsNullPtr = V.isNullPointer(); } - void set(APValue::LValueBase B, unsigned I = 0, bool BInvalid = false) { + void set(APValue::LValueBase B, unsigned I = 0, bool BInvalid = false, + bool IsNullPtr_ = false, uint64_t Offset_ = 0) { +#ifndef NDEBUG + // We only allow a few types of invalid bases. Enforce that here. + if (BInvalid) { + const auto *E = B.get<const Expr *>(); + assert((isa<MemberExpr>(E) || tryUnwrapAllocSizeCall(E)) && + "Unexpected type of invalid base"); + } +#endif + Base = B; - Offset = CharUnits::Zero(); + Offset = CharUnits::fromQuantity(Offset_); InvalidBase = BInvalid; CallIndex = I; Designator = SubobjectDesignator(getType(B)); + IsNullPtr = IsNullPtr_; } void setInvalid(APValue::LValueBase B, unsigned I = 0) { @@ -1112,7 +1234,7 @@ namespace { CheckSubobjectKind CSK) { if (Designator.Invalid) return false; - if (!Base) { + if (IsNullPtr) { Info.CCEDiag(E, diag::note_constexpr_null_subobject) << CSK; Designator.setInvalid(); @@ -1133,6 +1255,13 @@ namespace { if (checkSubobject(Info, E, isa<FieldDecl>(D) ? CSK_Field : CSK_Base)) Designator.addDeclUnchecked(D, Virtual); } + void addUnsizedArray(EvalInfo &Info, QualType ElemTy) { + assert(Designator.Entries.empty() && getType(Base)->isPointerType()); + assert(isBaseAnAllocSizeCall(Base) && + "Only alloc_size bases can have unsized arrays"); + Designator.FirstEntryIsAnUnsizedArray = true; + Designator.addUnsizedArrayUnchecked(ElemTy); + } void addArray(EvalInfo &Info, const Expr *E, const ConstantArrayType *CAT) { if (checkSubobject(Info, E, CSK_ArrayToPointer)) Designator.addArrayUnchecked(CAT); @@ -1141,9 +1270,22 @@ namespace { if (checkSubobject(Info, E, Imag ? CSK_Imag : CSK_Real)) Designator.addComplexUnchecked(EltTy, Imag); } - void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) { - if (N && checkNullPointer(Info, E, CSK_ArrayIndex)) - Designator.adjustIndex(Info, E, N); + void clearIsNullPointer() { + IsNullPtr = false; + } + void adjustOffsetAndIndex(EvalInfo &Info, const Expr *E, uint64_t Index, + CharUnits ElementSize) { + // Compute the new offset in the appropriate width. + Offset += Index * ElementSize; + if (Index && checkNullPointer(Info, E, CSK_ArrayIndex)) + Designator.adjustIndex(Info, E, Index); + if (Index) + clearIsNullPointer(); + } + void adjustOffset(CharUnits N) { + Offset += N; + if (N.getQuantity()) + clearIsNullPointer(); } }; @@ -1250,8 +1392,10 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E); static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, const LValue &This, const Expr *E, bool AllowNonLiteralTypes = false); -static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info); -static bool EvaluatePointer(const Expr *E, LValue &Result, EvalInfo &Info); +static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info, + bool InvalidBaseOK = false); +static bool EvaluatePointer(const Expr *E, LValue &Result, EvalInfo &Info, + bool InvalidBaseOK = false); static bool EvaluateMemberPointer(const Expr *E, MemberPtr &Result, EvalInfo &Info); static bool EvaluateTemporary(const Expr *E, LValue &Result, EvalInfo &Info); @@ -1483,8 +1627,17 @@ static bool CheckLiteralType(EvalInfo &Info, const Expr *E, // C++1y: A constant initializer for an object o [...] may also invoke // constexpr constructors for o and its subobjects even if those objects // are of non-literal class types. - if (Info.getLangOpts().CPlusPlus14 && This && - Info.EvaluatingDecl == This->getLValueBase()) + // + // C++11 missed this detail for aggregates, so classes like this: + // struct foo_t { union { int i; volatile int j; } u; }; + // are not (obviously) initializable like so: + // __attribute__((__require_constant_initialization__)) + // static const foo_t x = {{0}}; + // because "i" is a subobject with non-literal initialization (due to the + // volatile member of the union). See: + // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1677 + // Therefore, we use the C++1y behavior. + if (This && Info.EvaluatingDecl == This->getLValueBase()) return true; // Prvalue constant expressions must be of literal types. @@ -2018,7 +2171,7 @@ static bool HandleLValueMember(EvalInfo &Info, const Expr *E, LValue &LVal, } unsigned I = FD->getFieldIndex(); - LVal.Offset += Info.Ctx.toCharUnitsFromBits(RL->getFieldOffset(I)); + LVal.adjustOffset(Info.Ctx.toCharUnitsFromBits(RL->getFieldOffset(I))); LVal.addDecl(Info, E, FD); return true; } @@ -2072,9 +2225,7 @@ static bool HandleLValueArrayAdjustment(EvalInfo &Info, const Expr *E, if (!HandleSizeof(Info, E->getExprLoc(), EltTy, SizeOfPointee)) return false; - // Compute the new offset in the appropriate width. - LVal.Offset += Adjustment * SizeOfPointee; - LVal.adjustIndex(Info, E, Adjustment); + LVal.adjustOffsetAndIndex(Info, E, Adjustment, SizeOfPointee); return true; } @@ -2125,7 +2276,22 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, // If this is a local variable, dig out its value. if (Frame) { Result = Frame->getTemporary(VD); - assert(Result && "missing value for local variable"); + if (!Result) { + // Assume variables referenced within a lambda's call operator that were + // not declared within the call operator are captures and during checking + // of a potential constant expression, assume they are unknown constant + // expressions. + assert(isLambdaCallOperator(Frame->Callee) && + (VD->getDeclContext() != Frame->Callee || VD->isInitCapture()) && + "missing value for local variable"); + if (Info.checkingPotentialConstantExpression()) + return false; + // FIXME: implement capture evaluation during constant expr evaluation. + Info.FFDiag(E->getLocStart(), + diag::note_unimplemented_constexpr_lambda_feature_ast) + << "captures not currently allowed"; + return false; + } return true; } @@ -2196,7 +2362,14 @@ static unsigned getBaseIndex(const CXXRecordDecl *Derived, /// Extract the value of a character from a string literal. static APSInt extractStringLiteralCharacter(EvalInfo &Info, const Expr *Lit, uint64_t Index) { - // FIXME: Support ObjCEncodeExpr, MakeStringConstant + // FIXME: Support MakeStringConstant + if (const auto *ObjCEnc = dyn_cast<ObjCEncodeExpr>(Lit)) { + std::string Str; + Info.Ctx.getObjCEncodingForType(ObjCEnc->getEncodedType(), Str); + assert(Index <= Str.size() && "Index too large"); + return APSInt::getUnsigned(Str.c_str()[Index]); + } + if (auto PE = dyn_cast<PredefinedExpr>(Lit)) Lit = PE->getFunctionName(); const StringLiteral *S = cast<StringLiteral>(Lit); @@ -2771,6 +2944,9 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, } 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() && @@ -2892,7 +3068,6 @@ static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, // In C99, a CompoundLiteralExpr is an lvalue, and we defer evaluating the // initializer until now for such expressions. Such an expression can't be // an ICE in C, so this only matters for fold. - assert(!Info.getLangOpts().CPlusPlus && "lvalue compound literal in c++?"); if (Type.isVolatileQualified()) { Info.FFDiag(Conv); return false; @@ -3385,38 +3560,51 @@ enum EvalStmtResult { }; } -static bool EvaluateDecl(EvalInfo &Info, const Decl *D) { - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { - // We don't need to evaluate the initializer for a static local. - if (!VD->hasLocalStorage()) - return true; +static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) { + // We don't need to evaluate the initializer for a static local. + if (!VD->hasLocalStorage()) + return true; - LValue Result; - Result.set(VD, Info.CurrentCall->Index); - APValue &Val = Info.CurrentCall->createTemporary(VD, true); + LValue Result; + Result.set(VD, Info.CurrentCall->Index); + APValue &Val = Info.CurrentCall->createTemporary(VD, true); - const Expr *InitE = VD->getInit(); - if (!InitE) { - Info.FFDiag(D->getLocStart(), diag::note_constexpr_uninitialized) - << false << VD->getType(); - Val = APValue(); - return false; - } + const Expr *InitE = VD->getInit(); + if (!InitE) { + Info.FFDiag(VD->getLocStart(), diag::note_constexpr_uninitialized) + << false << VD->getType(); + Val = APValue(); + return false; + } - if (InitE->isValueDependent()) - return false; + if (InitE->isValueDependent()) + return false; - if (!EvaluateInPlace(Val, Info, Result, InitE)) { - // Wipe out any partially-computed value, to allow tracking that this - // evaluation failed. - Val = APValue(); - return false; - } + if (!EvaluateInPlace(Val, Info, Result, InitE)) { + // Wipe out any partially-computed value, to allow tracking that this + // evaluation failed. + Val = APValue(); + return false; } return true; } +static bool EvaluateDecl(EvalInfo &Info, const Decl *D) { + bool OK = true; + + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) + OK &= EvaluateVarDecl(Info, VD); + + if (const DecompositionDecl *DD = dyn_cast<DecompositionDecl>(D)) + for (auto *BD : DD->bindings()) + if (auto *VD = BD->getHoldingVar()) + OK &= EvaluateDecl(Info, VD); + + return OK; +} + + /// Evaluate a condition (either a variable declaration or an expression). static bool EvaluateCond(EvalInfo &Info, const VarDecl *CondDecl, const Expr *Cond, bool &Result) { @@ -4371,6 +4559,12 @@ public: Call.getLValueBase().dyn_cast<const ValueDecl*>()); if (!FD) return Error(Callee); + // Don't call function pointers which have been cast to some other type. + // Per DR (no number yet), the caller and callee can differ in noexcept. + if (!Info.Ctx.hasSameFunctionTypeIgnoringExceptionSpec( + CalleeType->getPointeeType(), FD->getType())) { + return Error(E); + } // Overloaded operator calls to member functions are represented as normal // calls with '*this' as the first argument. @@ -4386,11 +4580,42 @@ public: return false; This = &ThisVal; Args = Args.slice(1); + } else if (MD && MD->isLambdaStaticInvoker()) { + // Map the static invoker for the lambda back to the call operator. + // Conveniently, we don't have to slice out the 'this' argument (as is + // being done for the non-static case), since a static member function + // doesn't have an implicit argument passed in. + const CXXRecordDecl *ClosureClass = MD->getParent(); + assert( + ClosureClass->captures_begin() == ClosureClass->captures_end() && + "Number of captures must be zero for conversion to function-ptr"); + + const CXXMethodDecl *LambdaCallOp = + ClosureClass->getLambdaCallOperator(); + + // Set 'FD', the function that will be called below, to the call + // operator. If the closure object represents a generic lambda, find + // the corresponding specialization of the call operator. + + if (ClosureClass->isGenericLambda()) { + assert(MD->isFunctionTemplateSpecialization() && + "A generic lambda's static-invoker function must be a " + "template specialization"); + const TemplateArgumentList *TAL = MD->getTemplateSpecializationArgs(); + FunctionTemplateDecl *CallOpTemplate = + LambdaCallOp->getDescribedFunctionTemplate(); + void *InsertPos = nullptr; + FunctionDecl *CorrespondingCallOpSpecialization = + CallOpTemplate->findSpecialization(TAL->asArray(), InsertPos); + assert(CorrespondingCallOpSpecialization && + "We must always have a function call operator specialization " + "that corresponds to our static invoker specialization"); + FD = cast<CXXMethodDecl>(CorrespondingCallOpSpecialization); + } else + FD = LambdaCallOp; } - // Don't call function pointers which have been cast to some other type. - if (!Info.Ctx.hasSameType(CalleeType->getPointeeType(), FD->getType())) - return Error(E); + } else return Error(E); @@ -4578,6 +4803,7 @@ class LValueExprEvaluatorBase : public ExprEvaluatorBase<Derived> { protected: LValue &Result; + bool InvalidBaseOK; typedef LValueExprEvaluatorBase LValueExprEvaluatorBaseTy; typedef ExprEvaluatorBase<Derived> ExprEvaluatorBaseTy; @@ -4586,9 +4812,14 @@ protected: return true; } + bool evaluatePointer(const Expr *E, LValue &Result) { + return EvaluatePointer(E, Result, this->Info, InvalidBaseOK); + } + public: - LValueExprEvaluatorBase(EvalInfo &Info, LValue &Result) : - ExprEvaluatorBaseTy(Info), Result(Result) {} + LValueExprEvaluatorBase(EvalInfo &Info, LValue &Result, bool InvalidBaseOK) + : ExprEvaluatorBaseTy(Info), Result(Result), + InvalidBaseOK(InvalidBaseOK) {} bool Success(const APValue &V, const Expr *E) { Result.setFrom(this->Info.Ctx, V); @@ -4600,7 +4831,7 @@ public: QualType BaseTy; bool EvalOK; if (E->isArrow()) { - EvalOK = EvaluatePointer(E->getBase(), Result, this->Info); + EvalOK = evaluatePointer(E->getBase(), Result); BaseTy = E->getBase()->getType()->castAs<PointerType>()->getPointeeType(); } else if (E->getBase()->isRValue()) { assert(E->getBase()->getType()->isRecordType()); @@ -4611,7 +4842,7 @@ public: BaseTy = E->getBase()->getType(); } if (!EvalOK) { - if (!this->Info.allowInvalidBaseExpr()) + if (!InvalidBaseOK) return false; Result.setInvalid(E); return true; @@ -4683,7 +4914,7 @@ public: // * VarDecl // * FunctionDecl // - Literals -// * CompoundLiteralExpr in C +// * CompoundLiteralExpr in C (and in global scope in C++) // * StringLiteral // * CXXTypeidExpr // * PredefinedExpr @@ -4705,8 +4936,8 @@ namespace { class LValueExprEvaluator : public LValueExprEvaluatorBase<LValueExprEvaluator> { public: - LValueExprEvaluator(EvalInfo &Info, LValue &Result) : - LValueExprEvaluatorBaseTy(Info, Result) {} + LValueExprEvaluator(EvalInfo &Info, LValue &Result, bool InvalidBaseOK) : + LValueExprEvaluatorBaseTy(Info, Result, InvalidBaseOK) {} bool VisitVarDecl(const Expr *E, const VarDecl *VD); bool VisitUnaryPreIncDec(const UnaryOperator *UO); @@ -4759,10 +4990,11 @@ public: /// * function designators in C, and /// * "extern void" objects /// * @selector() expressions in Objective-C -static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info) { +static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info, + bool InvalidBaseOK) { assert(E->isGLValue() || E->getType()->isFunctionType() || E->getType()->isVoidType() || isa<ObjCSelectorExpr>(E)); - return LValueExprEvaluator(Info, Result).Visit(E); + return LValueExprEvaluator(Info, Result, InvalidBaseOK).Visit(E); } bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { @@ -4770,13 +5002,26 @@ bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { return Success(FD); if (const VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) return VisitVarDecl(E, VD); + if (const BindingDecl *BD = dyn_cast<BindingDecl>(E->getDecl())) + return Visit(BD->getBinding()); return Error(E); } + bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { CallStackFrame *Frame = nullptr; - if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1) - Frame = Info.CurrentCall; + if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1) { + // Only if a local variable was declared in the function currently being + // evaluated, do we expect to be able to find its value in the current + // frame. (Otherwise it was likely declared in an enclosing context and + // could either have a valid evaluatable value (for e.g. a constexpr + // variable) or be ill-formed (and trigger an appropriate evaluation + // diagnostic)). + if (Info.CurrentCall->Callee && + Info.CurrentCall->Callee->Equals(VD->getDeclContext())) { + Frame = Info.CurrentCall; + } + } if (!VD->getType()->isReferenceType()) { if (Frame) { @@ -4865,7 +5110,8 @@ bool LValueExprEvaluator::VisitMaterializeTemporaryExpr( bool LValueExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { - assert(!Info.getLangOpts().CPlusPlus && "lvalue compound literal in c++?"); + assert((!Info.getLangOpts().CPlusPlus || E->isFileScope()) && + "lvalue compound literal in c++?"); // Defer visiting the literal until the lvalue-to-rvalue conversion. We can // only see this when folding in C, so there's no standard to follow here. return Success(E); @@ -4909,7 +5155,7 @@ bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { if (E->getBase()->getType()->isVectorType()) return Error(E); - if (!EvaluatePointer(E->getBase(), Result, Info)) + if (!evaluatePointer(E->getBase(), Result)) return false; APSInt Index; @@ -4921,7 +5167,7 @@ bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { } bool LValueExprEvaluator::VisitUnaryDeref(const UnaryOperator *E) { - return EvaluatePointer(E->getSubExpr(), Result, Info); + return evaluatePointer(E->getSubExpr(), Result); } bool LValueExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { @@ -5000,26 +5246,139 @@ bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) { // Pointer Evaluation //===----------------------------------------------------------------------===// +/// \brief Attempts to compute the number of bytes available at the pointer +/// returned by a function with the alloc_size attribute. Returns true if we +/// were successful. Places an unsigned number into `Result`. +/// +/// This expects the given CallExpr to be a call to a function with an +/// alloc_size attribute. +static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx, + const CallExpr *Call, + llvm::APInt &Result) { + const AllocSizeAttr *AllocSize = getAllocSizeAttr(Call); + + // alloc_size args are 1-indexed, 0 means not present. + assert(AllocSize && AllocSize->getElemSizeParam() != 0); + unsigned SizeArgNo = AllocSize->getElemSizeParam() - 1; + unsigned BitsInSizeT = Ctx.getTypeSize(Ctx.getSizeType()); + if (Call->getNumArgs() <= SizeArgNo) + return false; + + auto EvaluateAsSizeT = [&](const Expr *E, APSInt &Into) { + if (!E->EvaluateAsInt(Into, Ctx, Expr::SE_AllowSideEffects)) + return false; + if (Into.isNegative() || !Into.isIntN(BitsInSizeT)) + return false; + Into = Into.zextOrSelf(BitsInSizeT); + return true; + }; + + APSInt SizeOfElem; + if (!EvaluateAsSizeT(Call->getArg(SizeArgNo), SizeOfElem)) + return false; + + if (!AllocSize->getNumElemsParam()) { + Result = std::move(SizeOfElem); + return true; + } + + APSInt NumberOfElems; + // Argument numbers start at 1 + unsigned NumArgNo = AllocSize->getNumElemsParam() - 1; + if (!EvaluateAsSizeT(Call->getArg(NumArgNo), NumberOfElems)) + return false; + + bool Overflow; + llvm::APInt BytesAvailable = SizeOfElem.umul_ov(NumberOfElems, Overflow); + if (Overflow) + return false; + + Result = std::move(BytesAvailable); + return true; +} + +/// \brief Convenience function. LVal's base must be a call to an alloc_size +/// function. +static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx, + const LValue &LVal, + llvm::APInt &Result) { + assert(isBaseAnAllocSizeCall(LVal.getLValueBase()) && + "Can't get the size of a non alloc_size function"); + const auto *Base = LVal.getLValueBase().get<const Expr *>(); + const CallExpr *CE = tryUnwrapAllocSizeCall(Base); + return getBytesReturnedByAllocSizeCall(Ctx, CE, Result); +} + +/// \brief Attempts to evaluate the given LValueBase as the result of a call to +/// a function with the alloc_size attribute. If it was possible to do so, this +/// function will return true, make Result's Base point to said function call, +/// and mark Result's Base as invalid. +static bool evaluateLValueAsAllocSize(EvalInfo &Info, APValue::LValueBase Base, + LValue &Result) { + if (Base.isNull()) + return false; + + // Because we do no form of static analysis, we only support const variables. + // + // Additionally, we can't support parameters, nor can we support static + // variables (in the latter case, use-before-assign isn't UB; in the former, + // we have no clue what they'll be assigned to). + const auto *VD = + dyn_cast_or_null<VarDecl>(Base.dyn_cast<const ValueDecl *>()); + if (!VD || !VD->isLocalVarDecl() || !VD->getType().isConstQualified()) + return false; + + const Expr *Init = VD->getAnyInitializer(); + if (!Init) + return false; + + const Expr *E = Init->IgnoreParens(); + if (!tryUnwrapAllocSizeCall(E)) + return false; + + // Store E instead of E unwrapped so that the type of the LValue's base is + // what the user wanted. + Result.setInvalid(E); + + QualType Pointee = E->getType()->castAs<PointerType>()->getPointeeType(); + Result.addUnsizedArray(Info, Pointee); + return true; +} + namespace { class PointerExprEvaluator : public ExprEvaluatorBase<PointerExprEvaluator> { LValue &Result; + bool InvalidBaseOK; bool Success(const Expr *E) { Result.set(E); return true; } + + bool evaluateLValue(const Expr *E, LValue &Result) { + return EvaluateLValue(E, Result, Info, InvalidBaseOK); + } + + bool evaluatePointer(const Expr *E, LValue &Result) { + return EvaluatePointer(E, Result, Info, InvalidBaseOK); + } + + bool visitNonBuiltinCallExpr(const CallExpr *E); public: - PointerExprEvaluator(EvalInfo &info, LValue &Result) - : ExprEvaluatorBaseTy(info), Result(Result) {} + PointerExprEvaluator(EvalInfo &info, LValue &Result, bool InvalidBaseOK) + : ExprEvaluatorBaseTy(info), Result(Result), + InvalidBaseOK(InvalidBaseOK) {} bool Success(const APValue &V, const Expr *E) { Result.setFrom(Info.Ctx, V); return true; } bool ZeroInitialization(const Expr *E) { - return Success((Expr*)nullptr); + auto Offset = Info.Ctx.getTargetNullPointerValue(E->getType()); + Result.set((Expr*)nullptr, 0, false, true, Offset); + return true; } bool VisitBinaryOperator(const BinaryOperator *E); @@ -5032,6 +5391,7 @@ public: bool VisitAddrLabelExpr(const AddrLabelExpr *E) { return Success(E); } bool VisitCallExpr(const CallExpr *E); + bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp); bool VisitBlockExpr(const BlockExpr *E) { if (!E->getBlockDecl()->hasCaptures()) return Success(E); @@ -5056,9 +5416,10 @@ public: }; } // end anonymous namespace -static bool EvaluatePointer(const Expr* E, LValue& Result, EvalInfo &Info) { +static bool EvaluatePointer(const Expr* E, LValue& Result, EvalInfo &Info, + bool InvalidBaseOK) { assert(E->isRValue() && E->getType()->hasPointerRepresentation()); - return PointerExprEvaluator(Info, Result).Visit(E); + return PointerExprEvaluator(Info, Result, InvalidBaseOK).Visit(E); } bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { @@ -5071,7 +5432,7 @@ bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (IExp->getType()->isPointerType()) std::swap(PExp, IExp); - bool EvalPtrOK = EvaluatePointer(PExp, Result, Info); + bool EvalPtrOK = evaluatePointer(PExp, Result); if (!EvalPtrOK && !Info.noteFailure()) return false; @@ -5089,7 +5450,7 @@ bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { } bool PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) { - return EvaluateLValue(E->getSubExpr(), Result, Info); + return evaluateLValue(E->getSubExpr(), Result); } bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { @@ -5117,11 +5478,13 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { else CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; } + if (E->getCastKind() == CK_AddressSpaceConversion && Result.IsNullPtr) + ZeroInitialization(E); return true; case CK_DerivedToBase: case CK_UncheckedDerivedToBase: - if (!EvaluatePointer(E->getSubExpr(), Result, Info)) + if (!evaluatePointer(E->getSubExpr(), Result)) return false; if (!Result.Base && Result.Offset.isZero()) return true; @@ -5158,6 +5521,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { Result.Offset = CharUnits::fromQuantity(N); Result.CallIndex = 0; Result.Designator.setInvalid(); + Result.IsNullPtr = false; return true; } else { // Cast is of an lvalue, no need to change value. @@ -5167,7 +5531,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { } case CK_ArrayToPointerDecay: if (SubExpr->isGLValue()) { - if (!EvaluateLValue(SubExpr, Result, Info)) + if (!evaluateLValue(SubExpr, Result)) return false; } else { Result.set(SubExpr, Info.CurrentCall->Index); @@ -5184,7 +5548,21 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { return true; case CK_FunctionToPointerDecay: - return EvaluateLValue(SubExpr, Result, Info); + return evaluateLValue(SubExpr, Result); + + case CK_LValueToRValue: { + LValue LVal; + if (!evaluateLValue(E->getSubExpr(), LVal)) + return false; + + APValue RVal; + // Note, we use the subexpression's type in order to retain cv-qualifiers. + if (!handleLValueToRValueConversion(Info, E, E->getSubExpr()->getType(), + LVal, RVal)) + return InvalidBaseOK && + evaluateLValueAsAllocSize(Info, LVal.Base, Result); + return Success(RVal, E); + } } return ExprEvaluatorBaseTy::VisitCastExpr(E); @@ -5222,18 +5600,40 @@ static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E) { return GetAlignOfType(Info, E->getType()); } +// To be clear: this happily visits unsupported builtins. Better name welcomed. +bool PointerExprEvaluator::visitNonBuiltinCallExpr(const CallExpr *E) { + if (ExprEvaluatorBaseTy::VisitCallExpr(E)) + return true; + + if (!(InvalidBaseOK && getAllocSizeAttr(E))) + return false; + + Result.setInvalid(E); + QualType PointeeTy = E->getType()->castAs<PointerType>()->getPointeeType(); + Result.addUnsizedArray(Info, PointeeTy); + return true; +} + bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) { if (IsStringLiteralCall(E)) return Success(E); - switch (E->getBuiltinCallee()) { + if (unsigned BuiltinOp = E->getBuiltinCallee()) + return VisitBuiltinCallExpr(E, BuiltinOp); + + return visitNonBuiltinCallExpr(E); +} + +bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, + unsigned BuiltinOp) { + switch (BuiltinOp) { case Builtin::BI__builtin_addressof: - return EvaluateLValue(E->getArg(0), Result, Info); + return evaluateLValue(E->getArg(0), Result); case Builtin::BI__builtin_assume_aligned: { // We need to be very careful here because: if the pointer does not have the // asserted alignment, then the behavior is undefined, and undefined // behavior is non-constant. - if (!EvaluatePointer(E->getArg(0), Result, Info)) + if (!evaluatePointer(E->getArg(0), Result)) return false; LValue OffsetResult(Result); @@ -5264,8 +5664,8 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) { if (BaseAlignment < Align) { Result.Designator.setInvalid(); - // FIXME: Quantities here cast to integers because the plural modifier - // does not work on APSInts yet. + // FIXME: Quantities here cast to integers because the plural modifier + // does not work on APSInts yet. CCEDiag(E->getArg(0), diag::note_constexpr_baa_insufficient_alignment) << 0 << (int) BaseAlignment.getQuantity() @@ -5294,8 +5694,95 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) { return true; } + + case Builtin::BIstrchr: + case Builtin::BIwcschr: + case Builtin::BImemchr: + case Builtin::BIwmemchr: + if (Info.getLangOpts().CPlusPlus11) + Info.CCEDiag(E, diag::note_constexpr_invalid_function) + << /*isConstexpr*/0 << /*isConstructor*/0 + << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'"); + else + Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); + // Fall through. + case Builtin::BI__builtin_strchr: + case Builtin::BI__builtin_wcschr: + case Builtin::BI__builtin_memchr: + case Builtin::BI__builtin_char_memchr: + case Builtin::BI__builtin_wmemchr: { + if (!Visit(E->getArg(0))) + return false; + APSInt Desired; + if (!EvaluateInteger(E->getArg(1), Desired, Info)) + return false; + uint64_t MaxLength = uint64_t(-1); + if (BuiltinOp != Builtin::BIstrchr && + BuiltinOp != Builtin::BIwcschr && + BuiltinOp != Builtin::BI__builtin_strchr && + BuiltinOp != Builtin::BI__builtin_wcschr) { + APSInt N; + if (!EvaluateInteger(E->getArg(2), N, Info)) + return false; + MaxLength = N.getExtValue(); + } + + QualType CharTy = E->getArg(0)->getType()->getPointeeType(); + + // Figure out what value we're actually looking for (after converting to + // the corresponding unsigned type if necessary). + uint64_t DesiredVal; + bool StopAtNull = false; + switch (BuiltinOp) { + case Builtin::BIstrchr: + case Builtin::BI__builtin_strchr: + // strchr compares directly to the passed integer, and therefore + // always fails if given an int that is not a char. + if (!APSInt::isSameValue(HandleIntToIntCast(Info, E, CharTy, + E->getArg(1)->getType(), + Desired), + Desired)) + return ZeroInitialization(E); + StopAtNull = true; + // Fall through. + case Builtin::BImemchr: + case Builtin::BI__builtin_memchr: + case Builtin::BI__builtin_char_memchr: + // memchr compares by converting both sides to unsigned char. That's also + // correct for strchr if we get this far (to cope with plain char being + // unsigned in the strchr case). + DesiredVal = Desired.trunc(Info.Ctx.getCharWidth()).getZExtValue(); + break; + + case Builtin::BIwcschr: + case Builtin::BI__builtin_wcschr: + StopAtNull = true; + // Fall through. + case Builtin::BIwmemchr: + case Builtin::BI__builtin_wmemchr: + // wcschr and wmemchr are given a wchar_t to look for. Just use it. + DesiredVal = Desired.getZExtValue(); + break; + } + + for (; MaxLength; --MaxLength) { + APValue Char; + if (!handleLValueToRValueConversion(Info, E, CharTy, Result, Char) || + !Char.isInt()) + return false; + if (Char.getInt().getZExtValue() == DesiredVal) + return true; + if (StopAtNull && !Char.getInt()) + break; + if (!HandleLValueArrayAdjustment(Info, E, Result, CharTy, 1)) + return false; + } + // Not found: return nullptr. + return ZeroInitialization(E); + } + default: - return ExprEvaluatorBaseTy::VisitCallExpr(E); + return visitNonBuiltinCallExpr(E); } } @@ -5418,6 +5905,7 @@ namespace { bool VisitCXXConstructExpr(const CXXConstructExpr *E) { return VisitCXXConstructExpr(E, E->getType()); } + bool VisitLambdaExpr(const LambdaExpr *E); bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E); bool VisitCXXConstructExpr(const CXXConstructExpr *E, QualType T); bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E); @@ -5535,6 +6023,9 @@ bool RecordExprEvaluator::VisitCastExpr(const CastExpr *E) { } bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { + if (E->isTransparent()) + return Visit(E->getInit(0)); + const RecordDecl *RD = E->getType()->castAs<RecordType>()->getDecl(); if (RD->isInvalidDecl()) return false; const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); @@ -5749,6 +6240,21 @@ bool RecordExprEvaluator::VisitCXXStdInitializerListExpr( return true; } +bool RecordExprEvaluator::VisitLambdaExpr(const LambdaExpr *E) { + const CXXRecordDecl *ClosureClass = E->getLambdaClass(); + if (ClosureClass->isInvalidDecl()) return false; + + if (Info.checkingPotentialConstantExpression()) return true; + if (E->capture_size()) { + Info.FFDiag(E, diag::note_unimplemented_constexpr_lambda_feature_ast) + << "can not evaluate lambda expressions with captures"; + return false; + } + // FIXME: Implement captures. + Result = APValue(APValue::UninitStruct(), /*NumBases*/0, /*NumFields*/0); + return true; +} + static bool EvaluateRecord(const Expr *E, const LValue &This, APValue &Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isRecordType() && @@ -5768,7 +6274,7 @@ class TemporaryExprEvaluator : public LValueExprEvaluatorBase<TemporaryExprEvaluator> { public: TemporaryExprEvaluator(EvalInfo &Info, LValue &Result) : - LValueExprEvaluatorBaseTy(Info, Result) {} + LValueExprEvaluatorBaseTy(Info, Result, false) {} /// Visit an expression which constructs the value of this temporary. bool VisitConstructExpr(const Expr *E) { @@ -5798,6 +6304,9 @@ public: bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E) { return VisitConstructExpr(E); } + bool VisitLambdaExpr(const LambdaExpr *E) { + return VisitConstructExpr(E); + } }; } // end anonymous namespace @@ -5890,7 +6399,7 @@ bool VectorExprEvaluator::VisitCastExpr(const CastExpr *E) { if (EltTy->isRealFloatingType()) { const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(EltTy); unsigned FloatEltSize = EltSize; - if (&Sem == &APFloat::x87DoubleExtended) + if (&Sem == &APFloat::x87DoubleExtended()) FloatEltSize = 80; for (unsigned i = 0; i < NElts; i++) { llvm::APInt Elt; @@ -6030,6 +6539,7 @@ namespace { return handleCallExpr(E, Result, &This); } bool VisitInitListExpr(const InitListExpr *E); + bool VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E); bool VisitCXXConstructExpr(const CXXConstructExpr *E); bool VisitCXXConstructExpr(const CXXConstructExpr *E, const LValue &Subobject, @@ -6112,6 +6622,35 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) { FillerExpr) && Success; } +bool ArrayExprEvaluator::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) { + if (E->getCommonExpr() && + !Evaluate(Info.CurrentCall->createTemporary(E->getCommonExpr(), false), + Info, E->getCommonExpr()->getSourceExpr())) + return false; + + auto *CAT = cast<ConstantArrayType>(E->getType()->castAsArrayTypeUnsafe()); + + uint64_t Elements = CAT->getSize().getZExtValue(); + Result = APValue(APValue::UninitArray(), Elements, Elements); + + LValue Subobject = This; + Subobject.addArray(Info, E, CAT); + + bool Success = true; + for (EvalInfo::ArrayInitLoopIndex Index(Info); Index != Elements; ++Index) { + if (!EvaluateInPlace(Result.getArrayInitializedElt(Index), + Info, Subobject, E->getSubExpr()) || + !HandleLValueArrayAdjustment(Info, E, Subobject, + CAT->getElementType(), 1)) { + if (!Info.noteFailure()) + return false; + Success = false; + } + } + + return Success; +} + bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { return VisitCXXConstructExpr(E, This, &Result, E->getType()); } @@ -6252,6 +6791,7 @@ public: } bool VisitCallExpr(const CallExpr *E); + bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp); bool VisitBinaryOperator(const BinaryOperator *E); bool VisitOffsetOfExpr(const OffsetOfExpr *E); bool VisitUnaryOperator(const UnaryOperator *E); @@ -6266,6 +6806,16 @@ public: bool VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E) { return Success(E->getValue(), E); } + + bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E) { + if (Info.ArrayInitIndex == uint64_t(-1)) { + // We were asked to evaluate this subexpression independent of the + // enclosing ArrayInitLoopExpr. We can't do that. + Info.FFDiag(E); + return false; + } + return Success(Info.ArrayInitIndex, E); + } // Note, GNU defines __null as an integer, not a pointer. bool VisitGNUNullExpr(const GNUNullExpr *E) { @@ -6290,8 +6840,6 @@ public: bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E); bool VisitSizeOfPackExpr(const SizeOfPackExpr *E); -private: - bool TryEvaluateBuiltinObjectSize(const CallExpr *E, unsigned Type); // FIXME: Missing: array subscript of vector, member of vector }; } // end anonymous namespace @@ -6563,7 +7111,7 @@ static QualType getObjectType(APValue::LValueBase B) { } /// A more selective version of E->IgnoreParenCasts for -/// TryEvaluateBuiltinObjectSize. This ignores some casts/parens that serve only +/// tryEvaluateBuiltinObjectSize. This ignores some casts/parens that serve only /// to change the type of E. /// Ex. For E = `(short*)((char*)(&foo))`, returns `&foo` /// @@ -6630,82 +7178,197 @@ static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) { } } + unsigned I = 0; QualType BaseType = getType(Base); - for (int I = 0, E = LVal.Designator.Entries.size(); I != E; ++I) { + if (LVal.Designator.FirstEntryIsAnUnsizedArray) { + assert(isBaseAnAllocSizeCall(Base) && + "Unsized array in non-alloc_size call?"); + // If this is an alloc_size base, we should ignore the initial array index + ++I; + BaseType = BaseType->castAs<PointerType>()->getPointeeType(); + } + + for (unsigned E = LVal.Designator.Entries.size(); I != E; ++I) { + const auto &Entry = LVal.Designator.Entries[I]; if (BaseType->isArrayType()) { // Because __builtin_object_size treats arrays as objects, we can ignore // the index iff this is the last array in the Designator. if (I + 1 == E) return true; - auto *CAT = cast<ConstantArrayType>(Ctx.getAsArrayType(BaseType)); - uint64_t Index = LVal.Designator.Entries[I].ArrayIndex; + const auto *CAT = cast<ConstantArrayType>(Ctx.getAsArrayType(BaseType)); + uint64_t Index = Entry.ArrayIndex; if (Index + 1 != CAT->getSize()) return false; BaseType = CAT->getElementType(); } else if (BaseType->isAnyComplexType()) { - auto *CT = BaseType->castAs<ComplexType>(); - uint64_t Index = LVal.Designator.Entries[I].ArrayIndex; + const auto *CT = BaseType->castAs<ComplexType>(); + uint64_t Index = Entry.ArrayIndex; if (Index != 1) return false; BaseType = CT->getElementType(); - } else if (auto *FD = getAsField(LVal.Designator.Entries[I])) { + } else if (auto *FD = getAsField(Entry)) { bool Invalid; if (!IsLastOrInvalidFieldDecl(FD, Invalid)) return Invalid; BaseType = FD->getType(); } else { - assert(getAsBaseClass(LVal.Designator.Entries[I]) != nullptr && - "Expecting cast to a base class"); + assert(getAsBaseClass(Entry) && "Expecting cast to a base class"); return false; } } return true; } -/// Tests to see if the LValue has a designator (that isn't necessarily valid). +/// Tests to see if the LValue has a user-specified designator (that isn't +/// necessarily valid). Note that this always returns 'true' if the LValue has +/// an unsized array as its first designator entry, because there's currently no +/// way to tell if the user typed *foo or foo[0]. static bool refersToCompleteObject(const LValue &LVal) { - if (LVal.Designator.Invalid || !LVal.Designator.Entries.empty()) + if (LVal.Designator.Invalid) return false; + if (!LVal.Designator.Entries.empty()) + return LVal.Designator.isMostDerivedAnUnsizedArray(); + if (!LVal.InvalidBase) return true; - auto *E = LVal.Base.dyn_cast<const Expr *>(); - (void)E; - assert(E != nullptr && isa<MemberExpr>(E)); - return false; + // If `E` is a MemberExpr, then the first part of the designator is hiding in + // the LValueBase. + const auto *E = LVal.Base.dyn_cast<const Expr *>(); + return !E || !isa<MemberExpr>(E); +} + +/// Attempts to detect a user writing into a piece of memory that's impossible +/// to figure out the size of by just using types. +static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const LValue &LVal) { + const SubobjectDesignator &Designator = LVal.Designator; + // Notes: + // - Users can only write off of the end when we have an invalid base. Invalid + // bases imply we don't know where the memory came from. + // - We used to be a bit more aggressive here; we'd only be conservative if + // 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 + // conservative with the last element in structs (if it's an array), so our + // current behavior is more compatible than a whitelisting approach would + // be. + return LVal.InvalidBase && + Designator.Entries.size() == Designator.MostDerivedPathLength && + Designator.MostDerivedIsArrayElement && + isDesignatorAtObjectEnd(Ctx, LVal); +} + +/// Converts the given APInt to CharUnits, assuming the APInt is unsigned. +/// Fails if the conversion would cause loss of precision. +static bool convertUnsignedAPIntToCharUnits(const llvm::APInt &Int, + CharUnits &Result) { + auto CharUnitsMax = std::numeric_limits<CharUnits::QuantityType>::max(); + if (Int.ugt(CharUnitsMax)) + return false; + Result = CharUnits::fromQuantity(Int.getZExtValue()); + return true; } -/// Tries to evaluate the __builtin_object_size for @p E. If successful, returns -/// true and stores the result in @p Size. +/// Helper for tryEvaluateBuiltinObjectSize -- Given an LValue, this will +/// determine how many bytes exist from the beginning of the object to either +/// the end of the current subobject, or the end of the object itself, depending +/// on what the LValue looks like + the value of Type. /// -/// If @p WasError is non-null, this will report whether the failure to evaluate -/// is to be treated as an Error in IntExprEvaluator. -static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type, - EvalInfo &Info, uint64_t &Size, - bool *WasError = nullptr) { - if (WasError != nullptr) - *WasError = false; - - auto Error = [&](const Expr *E) { - if (WasError != nullptr) - *WasError = true; - return false; - }; +/// If this returns false, the value of Result is undefined. +static bool determineEndOffset(EvalInfo &Info, SourceLocation ExprLoc, + unsigned Type, const LValue &LVal, + CharUnits &EndOffset) { + bool DetermineForCompleteObject = refersToCompleteObject(LVal); - auto Success = [&](uint64_t S, const Expr *E) { - Size = S; - return true; + auto CheckedHandleSizeof = [&](QualType Ty, CharUnits &Result) { + if (Ty.isNull() || Ty->isIncompleteType() || Ty->isFunctionType()) + return false; + return HandleSizeof(Info, ExprLoc, Ty, Result); }; + // We want to evaluate the size of the entire object. This is a valid fallback + // for when Type=1 and the designator is invalid, because we're asked for an + // upper-bound. + if (!(Type & 1) || LVal.Designator.Invalid || DetermineForCompleteObject) { + // Type=3 wants a lower bound, so we can't fall back to this. + if (Type == 3 && !DetermineForCompleteObject) + return false; + + llvm::APInt APEndOffset; + if (isBaseAnAllocSizeCall(LVal.getLValueBase()) && + getBytesReturnedByAllocSizeCall(Info.Ctx, LVal, APEndOffset)) + return convertUnsignedAPIntToCharUnits(APEndOffset, EndOffset); + + if (LVal.InvalidBase) + return false; + + QualType BaseTy = getObjectType(LVal.getLValueBase()); + return CheckedHandleSizeof(BaseTy, EndOffset); + } + + // We want to evaluate the size of a subobject. + const SubobjectDesignator &Designator = LVal.Designator; + + // The following is a moderately common idiom in C: + // + // struct Foo { int a; char c[1]; }; + // struct Foo *F = (struct Foo *)malloc(sizeof(struct Foo) + strlen(Bar)); + // strcpy(&F->c[0], Bar); + // + // In order to not break too much legacy code, we need to support it. + if (isUserWritingOffTheEnd(Info.Ctx, LVal)) { + // If we can resolve this to an alloc_size call, we can hand that back, + // because we know for certain how many bytes there are to write to. + llvm::APInt APEndOffset; + if (isBaseAnAllocSizeCall(LVal.getLValueBase()) && + getBytesReturnedByAllocSizeCall(Info.Ctx, LVal, APEndOffset)) + return convertUnsignedAPIntToCharUnits(APEndOffset, EndOffset); + + // If we cannot determine the size of the initial allocation, then we can't + // given an accurate upper-bound. However, we are still able to give + // conservative lower-bounds for Type=3. + if (Type == 1) + return false; + } + + CharUnits BytesPerElem; + if (!CheckedHandleSizeof(Designator.MostDerivedType, BytesPerElem)) + return false; + + // According to the GCC documentation, we want the size of the subobject + // denoted by the pointer. But that's not quite right -- what we actually + // want is the size of the immediately-enclosing array, if there is one. + int64_t ElemsRemaining; + if (Designator.MostDerivedIsArrayElement && + Designator.Entries.size() == Designator.MostDerivedPathLength) { + uint64_t ArraySize = Designator.getMostDerivedArraySize(); + uint64_t ArrayIndex = Designator.Entries.back().ArrayIndex; + ElemsRemaining = ArraySize <= ArrayIndex ? 0 : ArraySize - ArrayIndex; + } else { + ElemsRemaining = Designator.isOnePastTheEnd() ? 0 : 1; + } + + EndOffset = LVal.getLValueOffset() + BytesPerElem * ElemsRemaining; + return true; +} + +/// \brief Tries to evaluate the __builtin_object_size for @p E. If successful, +/// returns true and stores the result in @p Size. +/// +/// If @p WasError is non-null, this will report whether the failure to evaluate +/// is to be treated as an Error in IntExprEvaluator. +static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type, + EvalInfo &Info, uint64_t &Size) { // Determine the denoted object. - LValue Base; + LValue LVal; { // The operand of __builtin_object_size is never evaluated for side-effects. // If there are any, but we can determine the pointed-to object anyway, then // ignore the side-effects. SpeculativeEvaluationRAII SpeculativeEval(Info); - FoldOffsetRAII Fold(Info, Type & 1); + FoldOffsetRAII Fold(Info); if (E->isGLValue()) { // It's possible for us to be given GLValues if we're called via @@ -6713,118 +7376,41 @@ static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type, APValue RVal; if (!EvaluateAsRValue(Info, E, RVal)) return false; - Base.setFrom(Info.Ctx, RVal); - } else if (!EvaluatePointer(ignorePointerCastsAndParens(E), Base, Info)) + LVal.setFrom(Info.Ctx, RVal); + } else if (!EvaluatePointer(ignorePointerCastsAndParens(E), LVal, Info, + /*InvalidBaseOK=*/true)) return false; } - CharUnits BaseOffset = Base.getLValueOffset(); // If we point to before the start of the object, there are no accessible // bytes. - if (BaseOffset.isNegative()) - return Success(0, E); - - // In the case where we're not dealing with a subobject, we discard the - // subobject bit. - bool SubobjectOnly = (Type & 1) != 0 && !refersToCompleteObject(Base); - - // If Type & 1 is 0, we need to be able to statically guarantee that the bytes - // exist. If we can't verify the base, then we can't do that. - // - // As a special case, we produce a valid object size for an unknown object - // with a known designator if Type & 1 is 1. For instance: - // - // extern struct X { char buff[32]; int a, b, c; } *p; - // int a = __builtin_object_size(p->buff + 4, 3); // returns 28 - // int b = __builtin_object_size(p->buff + 4, 2); // returns 0, not 40 - // - // This matches GCC's behavior. - if (Base.InvalidBase && !SubobjectOnly) - return Error(E); - - // If we're not examining only the subobject, then we reset to a complete - // object designator - // - // If Type is 1 and we've lost track of the subobject, just find the complete - // object instead. (If Type is 3, that's not correct behavior and we should - // return 0 instead.) - LValue End = Base; - if (!SubobjectOnly || (End.Designator.Invalid && Type == 1)) { - QualType T = getObjectType(End.getLValueBase()); - if (T.isNull()) - End.Designator.setInvalid(); - else { - End.Designator = SubobjectDesignator(T); - End.Offset = CharUnits::Zero(); - } + if (LVal.getLValueOffset().isNegative()) { + Size = 0; + return true; } - // If it is not possible to determine which objects ptr points to at compile - // time, __builtin_object_size should return (size_t) -1 for type 0 or 1 - // and (size_t) 0 for type 2 or 3. - if (End.Designator.Invalid) - return false; - - // According to the GCC documentation, we want the size of the subobject - // denoted by the pointer. But that's not quite right -- what we actually - // want is the size of the immediately-enclosing array, if there is one. - int64_t AmountToAdd = 1; - if (End.Designator.MostDerivedIsArrayElement && - End.Designator.Entries.size() == End.Designator.MostDerivedPathLength) { - // We got a pointer to an array. Step to its end. - AmountToAdd = End.Designator.MostDerivedArraySize - - End.Designator.Entries.back().ArrayIndex; - } else if (End.Designator.isOnePastTheEnd()) { - // We're already pointing at the end of the object. - AmountToAdd = 0; - } - - QualType PointeeType = End.Designator.MostDerivedType; - assert(!PointeeType.isNull()); - if (PointeeType->isIncompleteType() || PointeeType->isFunctionType()) - return Error(E); - - if (!HandleLValueArrayAdjustment(Info, E, End, End.Designator.MostDerivedType, - AmountToAdd)) - return false; - - auto EndOffset = End.getLValueOffset(); - - // The following is a moderately common idiom in C: - // - // struct Foo { int a; char c[1]; }; - // struct Foo *F = (struct Foo *)malloc(sizeof(struct Foo) + strlen(Bar)); - // strcpy(&F->c[0], Bar); - // - // So, if we see that we're examining a 1-length (or 0-length) array at the - // end of a struct with an unknown base, we give up instead of breaking code - // that behaves this way. Note that we only do this when Type=1, because - // Type=3 is a lower bound, so answering conservatively is fine. - if (End.InvalidBase && SubobjectOnly && Type == 1 && - End.Designator.Entries.size() == End.Designator.MostDerivedPathLength && - End.Designator.MostDerivedIsArrayElement && - End.Designator.MostDerivedArraySize < 2 && - isDesignatorAtObjectEnd(Info.Ctx, End)) + CharUnits EndOffset; + if (!determineEndOffset(Info, E->getExprLoc(), Type, LVal, EndOffset)) return false; - if (BaseOffset > EndOffset) - return Success(0, E); - - return Success((EndOffset - BaseOffset).getQuantity(), E); + // If we've fallen outside of the end offset, just pretend there's nothing to + // write to/read from. + if (EndOffset <= LVal.getLValueOffset()) + Size = 0; + else + Size = (EndOffset - LVal.getLValueOffset()).getQuantity(); + return true; } -bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E, - unsigned Type) { - uint64_t Size; - bool WasError; - if (::tryEvaluateBuiltinObjectSize(E->getArg(0), Type, Info, Size, &WasError)) - return Success(Size, E); - if (WasError) - return Error(E); - return false; +bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { + if (unsigned BuiltinOp = E->getBuiltinCallee()) + return VisitBuiltinCallExpr(E, BuiltinOp); + + return ExprEvaluatorBaseTy::VisitCallExpr(E); } -bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { +bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, + unsigned BuiltinOp) { switch (unsigned BuiltinOp = E->getBuiltinCallee()) { default: return ExprEvaluatorBaseTy::VisitCallExpr(E); @@ -6835,8 +7421,9 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { E->getArg(1)->EvaluateKnownConstInt(Info.Ctx).getZExtValue(); assert(Type <= 3 && "unexpected type"); - if (TryEvaluateBuiltinObjectSize(E, Type)) - return true; + uint64_t Size; + if (tryEvaluateBuiltinObjectSize(E->getArg(0), Type, Info, Size)) + return Success(Size, E); if (E->getArg(0)->HasSideEffects(Info.Ctx)) return Success((Type & 2) ? 0 : -1, E); @@ -6849,7 +7436,7 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { case EvalInfo::EM_ConstantFold: case EvalInfo::EM_EvaluateForOverflow: case EvalInfo::EM_IgnoreSideEffects: - case EvalInfo::EM_DesignatorFold: + case EvalInfo::EM_OffsetFold: // Leave it to IR generation. return Error(E); case EvalInfo::EM_ConstantExpressionUnevaluated: @@ -6857,6 +7444,8 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { // Reduce it to a constant now. return Success((Type & 2) ? 0 : -1, E); } + + llvm_unreachable("unexpected EvalMode"); } case Builtin::BI__builtin_bswap16: @@ -6990,20 +7579,25 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { } case Builtin::BIstrlen: + case Builtin::BIwcslen: // A call to strlen is not a constant expression. if (Info.getLangOpts().CPlusPlus11) Info.CCEDiag(E, diag::note_constexpr_invalid_function) - << /*isConstexpr*/0 << /*isConstructor*/0 << "'strlen'"; + << /*isConstexpr*/0 << /*isConstructor*/0 + << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'"); else Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); // Fall through. - case Builtin::BI__builtin_strlen: { + case Builtin::BI__builtin_strlen: + case Builtin::BI__builtin_wcslen: { // As an extension, we support __builtin_strlen() as a constant expression, // and support folding strlen() to a constant. LValue String; if (!EvaluatePointer(E->getArg(0), String, Info)) return false; + QualType CharTy = E->getArg(0)->getType()->getPointeeType(); + // Fast path: if it's a string literal, search the string value. if (const StringLiteral *S = dyn_cast_or_null<StringLiteral>( String.getLValueBase().dyn_cast<const Expr *>())) { @@ -7012,7 +7606,9 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { StringRef Str = S->getBytes(); int64_t Off = String.Offset.getQuantity(); if (Off >= 0 && (uint64_t)Off <= (uint64_t)Str.size() && - S->getCharByteWidth() == 1) { + S->getCharByteWidth() == 1 && + // FIXME: Add fast-path for wchar_t too. + Info.Ctx.hasSameUnqualifiedType(CharTy, Info.Ctx.CharTy)) { Str = Str.substr(Off); StringRef::size_type Pos = Str.find(0); @@ -7026,7 +7622,6 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { } // Slow path: scan the bytes of the string looking for the terminating 0. - QualType CharTy = E->getArg(0)->getType()->getPointeeType(); for (uint64_t Strlen = 0; /**/; ++Strlen) { APValue Char; if (!handleLValueToRValueConversion(Info, E, CharTy, String, Char) || @@ -7039,6 +7634,66 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { } } + case Builtin::BIstrcmp: + case Builtin::BIwcscmp: + case Builtin::BIstrncmp: + case Builtin::BIwcsncmp: + case Builtin::BImemcmp: + case Builtin::BIwmemcmp: + // A call to strlen is not a constant expression. + if (Info.getLangOpts().CPlusPlus11) + Info.CCEDiag(E, diag::note_constexpr_invalid_function) + << /*isConstexpr*/0 << /*isConstructor*/0 + << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'"); + else + Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); + // Fall through. + case Builtin::BI__builtin_strcmp: + case Builtin::BI__builtin_wcscmp: + case Builtin::BI__builtin_strncmp: + case Builtin::BI__builtin_wcsncmp: + case Builtin::BI__builtin_memcmp: + case Builtin::BI__builtin_wmemcmp: { + LValue String1, String2; + if (!EvaluatePointer(E->getArg(0), String1, Info) || + !EvaluatePointer(E->getArg(1), String2, Info)) + return false; + + QualType CharTy = E->getArg(0)->getType()->getPointeeType(); + + uint64_t MaxLength = uint64_t(-1); + if (BuiltinOp != Builtin::BIstrcmp && + BuiltinOp != Builtin::BIwcscmp && + BuiltinOp != Builtin::BI__builtin_strcmp && + BuiltinOp != Builtin::BI__builtin_wcscmp) { + APSInt N; + if (!EvaluateInteger(E->getArg(2), N, Info)) + return false; + MaxLength = N.getExtValue(); + } + bool StopAtNull = (BuiltinOp != Builtin::BImemcmp && + BuiltinOp != Builtin::BIwmemcmp && + BuiltinOp != Builtin::BI__builtin_memcmp && + BuiltinOp != Builtin::BI__builtin_wmemcmp); + for (; MaxLength; --MaxLength) { + APValue Char1, Char2; + if (!handleLValueToRValueConversion(Info, E, CharTy, String1, Char1) || + !handleLValueToRValueConversion(Info, E, CharTy, String2, Char2) || + !Char1.isInt() || !Char2.isInt()) + return false; + if (Char1.getInt() != Char2.getInt()) + return Success(Char1.getInt() < Char2.getInt() ? -1 : 1, E); + if (StopAtNull && !Char1.getInt()) + return Success(0, E); + assert(!(StopAtNull && !Char2.getInt())); + if (!HandleLValueArrayAdjustment(Info, E, String1, CharTy, 1) || + !HandleLValueArrayAdjustment(Info, E, String2, CharTy, 1)) + return false; + } + // We hit the strncmp / memcmp limit. + return Success(0, E); + } + case Builtin::BI__atomic_always_lock_free: case Builtin::BI__atomic_is_lock_free: case Builtin::BI__c11_atomic_is_lock_free: { @@ -7160,9 +7815,7 @@ class DataRecursiveIntBinOpEvaluator { enum { AnyExprKind, BinOpKind, BinOpVisitedLHSKind } Kind; Job() = default; - Job(Job &&J) - : E(J.E), LHSResult(J.LHSResult), Kind(J.Kind), - SpecEvalRAII(std::move(J.SpecEvalRAII)) {} + Job(Job &&) = default; void startSpeculativeEval(EvalInfo &Info) { SpecEvalRAII = SpeculativeEvaluationRAII(Info); @@ -8037,8 +8690,10 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_IntegralComplexToFloatingComplex: case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLEvent: + case CK_ZeroToOCLQueue: case CK_NonAtomicToAtomic: case CK_AddressSpaceConversion: + case CK_IntToOCLSampler: llvm_unreachable("invalid cast kind for integral value"); case CK_BitCast: @@ -8113,8 +8768,13 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { return true; } - APSInt AsInt = Info.Ctx.MakeIntValue(LV.getLValueOffset().getQuantity(), - SrcType); + uint64_t V; + if (LV.isNullPointer()) + V = Info.Ctx.getTargetNullPointerValue(SrcType); + else + V = LV.getLValueOffset().getQuantity(); + + APSInt AsInt = Info.Ctx.MakeIntValue(V, SrcType); return Success(HandleIntToIntCast(Info, E, DestType, SrcType, AsInt), E); } @@ -8528,8 +9188,10 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_CopyAndAutoreleaseBlockObject: case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLEvent: + case CK_ZeroToOCLQueue: case CK_NonAtomicToAtomic: case CK_AddressSpaceConversion: + case CK_IntToOCLSampler: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: @@ -9341,6 +10003,8 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::CompoundLiteralExprClass: case Expr::ExtVectorElementExprClass: case Expr::DesignatedInitExprClass: + case Expr::ArrayInitLoopExprClass: + case Expr::ArrayInitIndexExprClass: case Expr::NoInitExprClass: case Expr::DesignatedInitUpdateExprClass: case Expr::ImplicitValueInitExprClass: @@ -9784,10 +10448,25 @@ bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result, bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx, const FunctionDecl *Callee, - ArrayRef<const Expr*> Args) const { + ArrayRef<const Expr*> Args, + const Expr *This) const { Expr::EvalStatus Status; EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpressionUnevaluated); + LValue ThisVal; + const LValue *ThisPtr = nullptr; + if (This) { +#ifndef NDEBUG + auto *MD = dyn_cast<CXXMethodDecl>(Callee); + assert(MD && "Don't provide `this` for non-methods."); + assert(!MD->isStatic() && "Don't provide `this` for static methods."); +#endif + if (EvaluateObjectArgument(Info, This, ThisVal)) + ThisPtr = &ThisVal; + if (Info.EvalStatus.HasSideEffects) + return false; + } + ArgVector ArgValues(Args.size()); for (ArrayRef<const Expr*>::iterator I = Args.begin(), E = Args.end(); I != E; ++I) { @@ -9800,7 +10479,7 @@ bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx, } // Build fake call to Callee. - CallStackFrame Frame(Info, Callee->getLocation(), Callee, /*This*/nullptr, + CallStackFrame Frame(Info, Callee->getLocation(), Callee, ThisPtr, ArgValues.data()); return Evaluate(Value, Info, this) && !Info.EvalStatus.HasSideEffects; } @@ -9877,5 +10556,5 @@ bool Expr::tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx, Expr::EvalStatus Status; EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold); - return ::tryEvaluateBuiltinObjectSize(this, Type, Info, Result); + return tryEvaluateBuiltinObjectSize(this, Type, Info, Result); } diff --git a/contrib/llvm/tools/clang/lib/AST/ExprObjC.cpp b/contrib/llvm/tools/clang/lib/AST/ExprObjC.cpp index 0936a81..31c1b3f 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprObjC.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprObjC.cpp @@ -278,7 +278,7 @@ ObjCMessageExpr *ObjCMessageExpr::alloc(const ASTContext &C, unsigned NumArgs, unsigned NumStoredSelLocs) { return (ObjCMessageExpr *)C.Allocate( totalSizeToAlloc<void *, SourceLocation>(NumArgs + 1, NumStoredSelLocs), - llvm::AlignOf<ObjCMessageExpr>::Alignment); + alignof(ObjCMessageExpr)); } void ObjCMessageExpr::getSelectorLocs( diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp index 8a2cc0f..692a455 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp @@ -63,9 +63,10 @@ public: CallOperator->getType()->getAs<FunctionProtoType>(); ASTContext &Context = CallOperator->getASTContext(); + FunctionProtoType::ExtProtoInfo EPI; + EPI.Variadic = Proto->isVariadic(); QualType Key = - Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), - FunctionProtoType::ExtProtoInfo()); + Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), EPI); Key = Context.getCanonicalType(Key); return ++ManglingNumbers[Key->castAs<FunctionProtoType>()]; } @@ -141,14 +142,6 @@ public: void addCopyConstructorForExceptionObject(CXXRecordDecl *RD, CXXConstructorDecl *CD) override {} - void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD, - unsigned ParmIdx, Expr *DAE) override {} - - Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, - unsigned ParmIdx) override { - return nullptr; - } - void addTypedefNameForUnnamedTagDecl(TagDecl *TD, TypedefNameDecl *DD) override {} @@ -163,8 +156,9 @@ public: return nullptr; } - MangleNumberingContext *createMangleNumberingContext() const override { - return new ItaniumNumberingContext(); + std::unique_ptr<MangleNumberingContext> + createMangleNumberingContext() const override { + return llvm::make_unique<ItaniumNumberingContext>(); } }; } diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp index 694fde3..ab3e49d 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp @@ -405,12 +405,14 @@ public: CXXNameMangler(CXXNameMangler &Outer, raw_ostream &Out_) : Context(Outer.Context), Out(Out_), NullOut(false), Structor(Outer.Structor), StructorType(Outer.StructorType), - SeqID(Outer.SeqID), AbiTagsRoot(AbiTags) {} + SeqID(Outer.SeqID), FunctionTypeDepth(Outer.FunctionTypeDepth), + AbiTagsRoot(AbiTags), Substitutions(Outer.Substitutions) {} CXXNameMangler(CXXNameMangler &Outer, llvm::raw_null_ostream &Out_) : Context(Outer.Context), Out(Out_), NullOut(true), Structor(Outer.Structor), StructorType(Outer.StructorType), - SeqID(Outer.SeqID), AbiTagsRoot(AbiTags) {} + SeqID(Outer.SeqID), FunctionTypeDepth(Outer.FunctionTypeDepth), + AbiTagsRoot(AbiTags), Substitutions(Outer.Substitutions) {} #if MANGLE_CHECKER ~CXXNameMangler() { @@ -458,11 +460,15 @@ private: void addSubstitution(QualType T); void addSubstitution(TemplateName Template); void addSubstitution(uintptr_t Ptr); + // Destructive copy substitutions from other mangler. + void extendSubstitutions(CXXNameMangler* Other); void mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, bool recursive = false); void mangleUnresolvedName(NestedNameSpecifier *qualifier, DeclarationName name, + const TemplateArgumentLoc *TemplateArgs, + unsigned NumTemplateArgs, unsigned KnownArity = UnknownArity); void mangleFunctionEncodingBareType(const FunctionDecl *FD); @@ -487,6 +493,7 @@ private: void mangleUnscopedTemplateName(TemplateName, const AbiTagList *AdditionalAbiTags); void mangleSourceName(const IdentifierInfo *II); + void mangleRegCallName(const IdentifierInfo *II); void mangleSourceNameWithAbiTags( const NamedDecl *ND, const AbiTagList *AdditionalAbiTags = nullptr); void mangleLocalName(const Decl *D, @@ -537,6 +544,8 @@ private: NestedNameSpecifier *qualifier, NamedDecl *firstQualifierLookup, DeclarationName name, + const TemplateArgumentLoc *TemplateArgs, + unsigned NumTemplateArgs, unsigned knownArity); void mangleCastExpression(const Expr *E, StringRef CastEncoding); void mangleInitListElements(const InitListExpr *InitList); @@ -593,7 +602,7 @@ bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { return false; const VarDecl *VD = dyn_cast<VarDecl>(D); - if (VD) { + if (VD && !isa<DecompositionDecl>(D)) { // C variables are not mangled. if (VD->isExternC()) return false; @@ -685,6 +694,10 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { // Output name with implicit tags and function encoding from temporary buffer. mangleNameWithAbiTags(FD, &AdditionalAbiTags); Out << FunctionEncodingStream.str().substr(EncodingPositionStart); + + // Function encoding could create new substitutions so we have to add + // temp mangled substitutions to main mangler. + extendSubstitutions(&FunctionEncodingMangler); } void CXXNameMangler::mangleFunctionEncodingBareType(const FunctionDecl *FD) { @@ -1151,9 +1164,10 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, /// Mangle an unresolved-name, which is generally used for names which /// weren't resolved to specific entities. -void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier, - DeclarationName name, - unsigned knownArity) { +void CXXNameMangler::mangleUnresolvedName( + NestedNameSpecifier *qualifier, DeclarationName name, + const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, + unsigned knownArity) { if (qualifier) mangleUnresolvedPrefix(qualifier); switch (name.getNameKind()) { // <base-unresolved-name> ::= <simple-id> @@ -1181,6 +1195,11 @@ void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier, case DeclarationName::ObjCZeroArgSelector: llvm_unreachable("Can't mangle Objective-C selector names here!"); } + + // The <simple-id> and on <operator-name> productions end in an optional + // <template-args>. + if (TemplateArgs) + mangleTemplateArgs(TemplateArgs, NumTemplateArgs); } void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, @@ -1193,7 +1212,26 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // ::= <source-name> switch (Name.getNameKind()) { case DeclarationName::Identifier: { - if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) { + const IdentifierInfo *II = Name.getAsIdentifierInfo(); + + // We mangle decomposition declarations as the names of their bindings. + if (auto *DD = dyn_cast<DecompositionDecl>(ND)) { + // FIXME: Non-standard mangling for decomposition declarations: + // + // <unqualified-name> ::= DC <source-name>* E + // + // These can never be referenced across translation units, so we do + // not need a cross-vendor mangling for anything other than demanglers. + // Proposed on cxx-abi-dev on 2016-08-12 + Out << "DC"; + for (auto *BD : DD->bindings()) + mangleSourceName(BD->getDeclName().getAsIdentifierInfo()); + Out << 'E'; + writeAbiTags(ND, AdditionalAbiTags); + break; + } + + if (II) { // We must avoid conflicts between internally- and externally- // linked variable and function declaration names in the same TU: // void test() { extern void foo(); } @@ -1204,7 +1242,15 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, getEffectiveDeclContext(ND)->isFileContext()) Out << 'L'; - mangleSourceName(II); + auto *FD = dyn_cast<FunctionDecl>(ND); + bool IsRegCall = FD && + FD->getType()->castAs<FunctionType>()->getCallConv() == + clang::CC_X86RegCall; + if (IsRegCall) + mangleRegCallName(II); + else + mangleSourceName(II); + writeAbiTags(ND, AdditionalAbiTags); break; } @@ -1378,6 +1424,14 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, } } +void CXXNameMangler::mangleRegCallName(const IdentifierInfo *II) { + // <source-name> ::= <positive length number> __regcall3__ <identifier> + // <number> ::= [n] <non-negative decimal integer> + // <identifier> ::= <unqualified source code identifier> + Out << II->getLength() + sizeof("__regcall3__") - 1 << "__regcall3__" + << II->getName(); +} + void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) { // <source-name> ::= <positive length number> <identifier> // <number> ::= [n] <non-negative decimal integer> @@ -1471,7 +1525,7 @@ void CXXNameMangler::mangleLocalName(const Decl *D, // numbering will be local to the particular argument in which it appears // -- other default arguments do not affect its encoding. const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD); - if (CXXRD->isLambda()) { + if (CXXRD && CXXRD->isLambda()) { if (const ParmVarDecl *Parm = dyn_cast_or_null<ParmVarDecl>(CXXRD->getLambdaContextDecl())) { if (const FunctionDecl *Func @@ -1820,6 +1874,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: + case Type::ObjCTypeParam: case Type::Atomic: case Type::Pipe: llvm_unreachable("type is illegal as a nested name specifier"); @@ -2207,6 +2262,22 @@ void CXXNameMangler::mangleType(QualType T) { // they aren't written. // - Conversions on non-type template arguments need to be expressed, since // they can affect the mangling of sizeof/alignof. + // + // FIXME: This is wrong when mapping to the canonical type for a dependent + // type discards instantiation-dependent portions of the type, such as for: + // + // template<typename T, int N> void f(T (&)[sizeof(N)]); + // template<typename T> void f(T() throw(typename T::type)); (pre-C++17) + // + // It's also wrong in the opposite direction when instantiation-dependent, + // canonically-equivalent types differ in some irrelevant portion of inner + // type sugar. In such cases, we fail to form correct substitutions, eg: + // + // template<int N> void f(A<sizeof(N)> *, A<sizeof(N)> (*)); + // + // We should instead canonicalize the non-instantiation-dependent parts, + // regardless of whether the type as a whole is dependent or instantiation + // dependent. if (!T->isInstantiationDependentType() || T->isDependentType()) T = T.getCanonicalType(); else { @@ -2443,6 +2514,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) { case CC_X86Pascal: case CC_X86_64Win64: case CC_X86_64SysV: + case CC_X86RegCall: case CC_AAPCS: case CC_AAPCS_VFP: case CC_IntelOclBicc: @@ -2509,6 +2581,24 @@ void CXXNameMangler::mangleType(const FunctionProtoType *T) { // e.g. "const" in "int (A::*)() const". mangleQualifiers(Qualifiers::fromCVRMask(T->getTypeQuals())); + // Mangle instantiation-dependent exception-specification, if present, + // per cxx-abi-dev proposal on 2016-10-11. + if (T->hasInstantiationDependentExceptionSpec()) { + if (T->getExceptionSpecType() == EST_ComputedNoexcept) { + Out << "DO"; + mangleExpression(T->getNoexceptExpr()); + Out << "E"; + } else { + assert(T->getExceptionSpecType() == EST_Dynamic); + Out << "Dw"; + for (auto ExceptTy : T->exceptions()) + mangleType(ExceptTy); + Out << "E"; + } + } else if (T->isNothrow(getASTContext())) { + Out << "Do"; + } + Out << 'F'; // FIXME: We don't have enough information in the AST to produce the 'Y' @@ -3115,12 +3205,14 @@ void CXXNameMangler::mangleMemberExpr(const Expr *base, NestedNameSpecifier *qualifier, NamedDecl *firstQualifierLookup, DeclarationName member, + const TemplateArgumentLoc *TemplateArgs, + unsigned NumTemplateArgs, unsigned arity) { // <expression> ::= dt <expression> <unresolved-name> // ::= pt <expression> <unresolved-name> if (base) mangleMemberExprBase(base, isArrow); - mangleUnresolvedName(qualifier, member, arity); + mangleUnresolvedName(qualifier, member, TemplateArgs, NumTemplateArgs, arity); } /// Look at the callee of the given call expression and determine if @@ -3209,6 +3301,8 @@ recurse: case Expr::AddrLabelExprClass: case Expr::DesignatedInitUpdateExprClass: case Expr::ImplicitValueInitExprClass: + case Expr::ArrayInitLoopExprClass: + case Expr::ArrayInitIndexExprClass: case Expr::NoInitExprClass: case Expr::ParenListExprClass: case Expr::LambdaExprClass: @@ -3418,7 +3512,9 @@ recurse: const MemberExpr *ME = cast<MemberExpr>(E); mangleMemberExpr(ME->getBase(), ME->isArrow(), ME->getQualifier(), nullptr, - ME->getMemberDecl()->getDeclName(), Arity); + ME->getMemberDecl()->getDeclName(), + ME->getTemplateArgs(), ME->getNumTemplateArgs(), + Arity); break; } @@ -3426,9 +3522,9 @@ recurse: const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E); mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(), ME->isArrow(), ME->getQualifier(), nullptr, - ME->getMemberName(), Arity); - if (ME->hasExplicitTemplateArgs()) - mangleTemplateArgs(ME->getTemplateArgs(), ME->getNumTemplateArgs()); + ME->getMemberName(), + ME->getTemplateArgs(), ME->getNumTemplateArgs(), + Arity); break; } @@ -3438,21 +3534,17 @@ recurse: mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(), ME->isArrow(), ME->getQualifier(), ME->getFirstQualifierFoundInScope(), - ME->getMember(), Arity); - if (ME->hasExplicitTemplateArgs()) - mangleTemplateArgs(ME->getTemplateArgs(), ME->getNumTemplateArgs()); + ME->getMember(), + ME->getTemplateArgs(), ME->getNumTemplateArgs(), + Arity); break; } case Expr::UnresolvedLookupExprClass: { const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E); - mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), Arity); - - // All the <unresolved-name> productions end in a - // base-unresolved-name, where <template-args> are just tacked - // onto the end. - if (ULE->hasExplicitTemplateArgs()) - mangleTemplateArgs(ULE->getTemplateArgs(), ULE->getNumTemplateArgs()); + mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), + ULE->getTemplateArgs(), ULE->getNumTemplateArgs(), + Arity); break; } @@ -3707,7 +3799,10 @@ recurse: case Expr::CXXOperatorCallExprClass: { const CXXOperatorCallExpr *CE = cast<CXXOperatorCallExpr>(E); unsigned NumArgs = CE->getNumArgs(); - mangleOperatorName(CE->getOperator(), /*Arity=*/NumArgs); + // A CXXOperatorCallExpr for OO_Arrow models only semantics, not syntax + // (the enclosing MemberExpr covers the syntactic portion). + if (CE->getOperator() != OO_Arrow) + mangleOperatorName(CE->getOperator(), /*Arity=*/NumArgs); // Mangle the arguments. for (unsigned i = 0; i != NumArgs; ++i) mangleExpression(CE->getArg(i)); @@ -3768,13 +3863,9 @@ recurse: case Expr::DependentScopeDeclRefExprClass: { const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E); - mangleUnresolvedName(DRE->getQualifier(), DRE->getDeclName(), Arity); - - // All the <unresolved-name> productions end in a - // base-unresolved-name, where <template-args> are just tacked - // onto the end. - if (DRE->hasExplicitTemplateArgs()) - mangleTemplateArgs(DRE->getTemplateArgs(), DRE->getNumTemplateArgs()); + mangleUnresolvedName(DRE->getQualifier(), DRE->getDeclName(), + DRE->getTemplateArgs(), DRE->getNumTemplateArgs(), + Arity); break; } @@ -4406,6 +4497,14 @@ void CXXNameMangler::addSubstitution(uintptr_t Ptr) { Substitutions[Ptr] = SeqID++; } +void CXXNameMangler::extendSubstitutions(CXXNameMangler* Other) { + assert(Other->SeqID >= SeqID && "Must be superset of substitutions!"); + if (Other->SeqID > SeqID) { + Substitutions.swap(Other->Substitutions); + SeqID = Other->SeqID; + } +} + CXXNameMangler::AbiTagList CXXNameMangler::makeFunctionReturnTypeTags(const FunctionDecl *FD) { // When derived abi tags are disabled there is no need to make any list. diff --git a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp index ee24173..05dd886 100644 --- a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp @@ -52,6 +52,7 @@ void MangleContext::anchor() { } enum CCMangling { CCM_Other, CCM_Fast, + CCM_RegCall, CCM_Vector, CCM_Std }; @@ -152,6 +153,8 @@ void MangleContext::mangleName(const NamedDecl *D, raw_ostream &Out) { Out << '_'; else if (CC == CCM_Fast) Out << '@'; + else if (CC == CCM_RegCall) + Out << "__regcall3__"; if (!MCXX) Out << D->getIdentifier()->getName(); diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp index 3ae0453..73324e4 100644 --- a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp @@ -67,8 +67,6 @@ public: class MicrosoftCXXABI : public CXXABI { ASTContext &Context; llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor; - llvm::SmallDenseMap<std::pair<const CXXConstructorDecl *, unsigned>, Expr *> - CtorToDefaultArgExpr; llvm::SmallDenseMap<TagDecl *, DeclaratorDecl *> UnnamedTagDeclToDeclaratorDecl; @@ -92,16 +90,6 @@ public: llvm_unreachable("unapplicable to the MS ABI"); } - void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD, - unsigned ParmIdx, Expr *DAE) override { - CtorToDefaultArgExpr[std::make_pair(CD, ParmIdx)] = DAE; - } - - Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, - unsigned ParmIdx) override { - return CtorToDefaultArgExpr[std::make_pair(CD, ParmIdx)]; - } - const CXXConstructorDecl * getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override { return RecordToCopyCtor[RD]; @@ -143,8 +131,9 @@ public: const_cast<TagDecl *>(TD->getCanonicalDecl())); } - MangleNumberingContext *createMangleNumberingContext() const override { - return new MicrosoftNumberingContext(); + std::unique_ptr<MangleNumberingContext> + createMangleNumberingContext() const override { + return llvm::make_unique<MicrosoftNumberingContext>(); } }; } diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp index 351997e..76c368d 100644 --- a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp @@ -66,6 +66,16 @@ struct msvc_hashing_ostream : public llvm::raw_svector_ostream { } }; +static const DeclContext * +getLambdaDefaultArgumentDeclContext(const Decl *D) { + if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) + if (RD->isLambda()) + if (const auto *Parm = + dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl())) + return Parm->getDeclContext(); + return nullptr; +} + /// \brief Retrieve the declaration context that should be used when mangling /// the given declaration. static const DeclContext *getEffectiveDeclContext(const Decl *D) { @@ -75,12 +85,8 @@ static const DeclContext *getEffectiveDeclContext(const Decl *D) { // not the case: the lambda closure type ends up living in the context // where the function itself resides, because the function declaration itself // had not yet been created. Fix the context here. - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { - if (RD->isLambda()) - if (ParmVarDecl *ContextParam = - dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl())) - return ContextParam->getDeclContext(); - } + if (const auto *LDADC = getLambdaDefaultArgumentDeclContext(D)) + return LDADC; // Perform the same check for block literals. if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { @@ -103,21 +109,13 @@ static const DeclContext *getEffectiveParentContext(const DeclContext *DC) { static const FunctionDecl *getStructor(const NamedDecl *ND) { if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(ND)) - return FTD->getTemplatedDecl(); + return FTD->getTemplatedDecl()->getCanonicalDecl(); const auto *FD = cast<FunctionDecl>(ND); if (const auto *FTD = FD->getPrimaryTemplate()) - return FTD->getTemplatedDecl(); + return FTD->getTemplatedDecl()->getCanonicalDecl(); - return FD; -} - -static bool isLambda(const NamedDecl *ND) { - const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND); - if (!Record) - return false; - - return Record->isLambda(); + return FD->getCanonicalDecl(); } /// MicrosoftMangleContextImpl - Overrides the default MangleContext for the @@ -200,9 +198,11 @@ public: // Lambda closure types are already numbered, give out a phony number so // that they demangle nicely. - if (isLambda(ND)) { - disc = 1; - return true; + if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) { + if (RD->isLambda()) { + disc = 1; + return true; + } } // Use the canonical number for externally visible decls. @@ -312,6 +312,10 @@ public: void mangleNestedName(const NamedDecl *ND); private: + bool isStructorDecl(const NamedDecl *ND) const { + return ND == Structor || getStructor(ND) == Structor; + } + void mangleUnqualifiedName(const NamedDecl *ND) { mangleUnqualifiedName(ND, ND->getDeclName()); } @@ -394,7 +398,8 @@ bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { if (!getASTContext().getLangOpts().CPlusPlus) return false; - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + const VarDecl *VD = dyn_cast<VarDecl>(D); + if (VD && !isa<DecompositionDecl>(D)) { // C variables are not mangled. if (VD->isExternC()) return false; @@ -780,6 +785,21 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, } } + if (const DecompositionDecl *DD = dyn_cast<DecompositionDecl>(ND)) { + // FIXME: Invented mangling for decomposition declarations: + // [X,Y,Z] + // where X,Y,Z are the names of the bindings. + llvm::SmallString<128> Name("["); + for (auto *BD : DD->bindings()) { + if (Name.size() > 1) + Name += ','; + Name += BD->getDeclName().getAsIdentifierInfo()->getName(); + } + Name += ']'; + mangleSourceName(Name); + break; + } + if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) { // We must have an anonymous union or struct declaration. const CXXRecordDecl *RD = VD->getType()->getAsCXXRecordDecl(); @@ -808,9 +828,24 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) { if (Record->isLambda()) { llvm::SmallString<10> Name("<lambda_"); + + Decl *LambdaContextDecl = Record->getLambdaContextDecl(); + unsigned LambdaManglingNumber = Record->getLambdaManglingNumber(); unsigned LambdaId; - if (Record->getLambdaManglingNumber()) - LambdaId = Record->getLambdaManglingNumber(); + const ParmVarDecl *Parm = + dyn_cast_or_null<ParmVarDecl>(LambdaContextDecl); + const FunctionDecl *Func = + Parm ? dyn_cast<FunctionDecl>(Parm->getDeclContext()) : nullptr; + + if (Func) { + unsigned DefaultArgNo = + Func->getNumParams() - Parm->getFunctionScopeIndex(); + Name += llvm::utostr(DefaultArgNo); + Name += "_"; + } + + if (LambdaManglingNumber) + LambdaId = LambdaManglingNumber; else LambdaId = Context.getLambdaId(Record); @@ -818,25 +853,42 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, Name += ">"; mangleSourceName(Name); + + // If the context of a closure type is an initializer for a class + // member (static or nonstatic), it is encoded in a qualified name. + if (LambdaManglingNumber && LambdaContextDecl) { + if ((isa<VarDecl>(LambdaContextDecl) || + isa<FieldDecl>(LambdaContextDecl)) && + LambdaContextDecl->getDeclContext()->isRecord()) { + mangleUnqualifiedName(cast<NamedDecl>(LambdaContextDecl)); + } + } break; } } - llvm::SmallString<64> Name("<unnamed-type-"); + llvm::SmallString<64> Name; if (DeclaratorDecl *DD = Context.getASTContext().getDeclaratorForUnnamedTagDecl(TD)) { // Anonymous types without a name for linkage purposes have their // declarator mangled in if they have one. + Name += "<unnamed-type-"; Name += DD->getName(); } else if (TypedefNameDecl *TND = Context.getASTContext().getTypedefNameForUnnamedTagDecl( TD)) { // Anonymous types without a name for linkage purposes have their // associate typedef mangled in if they have one. + Name += "<unnamed-type-"; Name += TND->getName(); + } else if (auto *ED = dyn_cast<EnumDecl>(TD)) { + auto EnumeratorI = ED->enumerator_begin(); + assert(EnumeratorI != ED->enumerator_end()); + Name += "<unnamed-enum-"; + Name += EnumeratorI->getName(); } else { // Otherwise, number the types using a $S prefix. - Name += "$S"; + Name += "<unnamed-type-$S"; Name += llvm::utostr(Context.getAnonymousStructId(TD) + 1); } Name += ">"; @@ -850,7 +902,7 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, llvm_unreachable("Can't mangle Objective-C selector names here!"); case DeclarationName::CXXConstructorName: - if (Structor == getStructor(ND)) { + if (isStructorDecl(ND)) { if (StructorType == Ctor_CopyingClosure) { Out << "?_O"; return; @@ -864,7 +916,7 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, return; case DeclarationName::CXXDestructorName: - if (ND == Structor) + if (isStructorDecl(ND)) // If the named decl is the C++ destructor we're mangling, // use the type we were given. mangleCXXDtorType(static_cast<CXXDtorType>(StructorType)); @@ -921,7 +973,6 @@ void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) { // for how this should be done. Out << "__block_invoke" << Context.getBlockId(BD, false); Out << '@'; - continue; } else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) { mangleObjCMethodName(Method); } else if (isa<NamedDecl>(DC)) { @@ -929,8 +980,15 @@ void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { mangle(FD, "?"); break; - } else + } else { mangleUnqualifiedName(ND); + // Lambdas in default arguments conceptually belong to the function the + // parameter corresponds to. + if (const auto *LDADC = getLambdaDefaultArgumentDeclContext(ND)) { + DC = LDADC; + continue; + } + } } DC = DC->getParent(); } @@ -1073,6 +1131,8 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, case OO_Array_New: Out << "?_U"; break; // <operator-name> ::= ?_V # delete[] case OO_Array_Delete: Out << "?_V"; break; + // <operator-name> ::= ?__L # co_await + case OO_Coawait: Out << "?__L"; break; case OO_Conditional: { DiagnosticsEngine &Diags = Context.getDiags(); @@ -1082,14 +1142,6 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, break; } - case OO_Coawait: { - DiagnosticsEngine &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle this operator co_await yet"); - Diags.Report(Loc, DiagID); - break; - } - case OO_None: case NUM_OVERLOADED_OPERATORS: llvm_unreachable("Not an overloaded operator"); @@ -1814,7 +1866,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, IsStructor = true; IsCtorClosure = (StructorType == Ctor_CopyingClosure || StructorType == Ctor_DefaultClosure) && - getStructor(MD) == Structor; + isStructorDecl(MD); if (IsCtorClosure) CC = getASTContext().getDefaultCallingConvention( /*IsVariadic=*/false, /*IsCXXMethod=*/true); @@ -1835,7 +1887,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, // <return-type> ::= <type> // ::= @ # structors (they have no declared return type) if (IsStructor) { - if (isa<CXXDestructorDecl>(D) && D == Structor && + if (isa<CXXDestructorDecl>(D) && isStructorDecl(D) && StructorType == Dtor_Deleting) { // The scalar deleting destructor takes an extra int argument. // However, the FunctionType generated has 0 arguments. @@ -1993,6 +2045,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) { // ::= I # __fastcall // ::= J # __export __fastcall // ::= Q # __vectorcall + // ::= w # __regcall // The 'export' calling conventions are from a bygone era // (*cough*Win16*cough*) when functions were declared for export with // that keyword. (It didn't actually export them, it just made them so @@ -2010,6 +2063,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) { case CC_X86StdCall: Out << 'G'; break; case CC_X86FastCall: Out << 'I'; break; case CC_X86VectorCall: Out << 'Q'; break; + case CC_X86RegCall: Out << 'w'; break; } } void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) { diff --git a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp index 82809d7..514c7c9 100644 --- a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp +++ b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp @@ -34,8 +34,8 @@ NestedNameSpecifier::FindOrInsert(const ASTContext &Context, NestedNameSpecifier *NNS = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos); if (!NNS) { - NNS = new (Context, llvm::alignOf<NestedNameSpecifier>()) - NestedNameSpecifier(Mockup); + NNS = + new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(Mockup); Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos); } @@ -113,8 +113,7 @@ NestedNameSpecifier * NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) { if (!Context.GlobalNestedNameSpecifier) Context.GlobalNestedNameSpecifier = - new (Context, llvm::alignOf<NestedNameSpecifier>()) - NestedNameSpecifier(); + new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(); return Context.GlobalNestedNameSpecifier; } @@ -155,7 +154,7 @@ NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { /// \brief Retrieve the namespace stored in this nested name specifier. NamespaceDecl *NestedNameSpecifier::getAsNamespace() const { - if (Prefix.getInt() == StoredDecl) + if (Prefix.getInt() == StoredDecl) return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier)); return nullptr; @@ -163,7 +162,7 @@ NamespaceDecl *NestedNameSpecifier::getAsNamespace() const { /// \brief Retrieve the namespace alias stored in this nested name specifier. NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const { - if (Prefix.getInt() == StoredDecl) + if (Prefix.getInt() == StoredDecl) return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier)); return nullptr; @@ -687,7 +686,7 @@ NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const { // FIXME: After copying the source-location information, should we free // our (temporary) buffer and adopt the ASTContext-allocated memory? // Doing so would optimize repeated calls to getWithLocInContext(). - void *Mem = Context.Allocate(BufferSize, llvm::alignOf<void *>()); + void *Mem = Context.Allocate(BufferSize, alignof(void *)); memcpy(Mem, Buffer, BufferSize); return NestedNameSpecifierLoc(Representation, Mem); } diff --git a/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp b/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp index d04ba72..a28b9f3 100644 --- a/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp +++ b/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp @@ -732,38 +732,113 @@ OMPFromClause *OMPFromClause::CreateEmpty(const ASTContext &C, unsigned NumVars, NumComponentLists, NumComponents); } -OMPUseDevicePtrClause *OMPUseDevicePtrClause::Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc, - ArrayRef<Expr *> VL) { - void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size())); - OMPUseDevicePtrClause *Clause = - new (Mem) OMPUseDevicePtrClause(StartLoc, LParenLoc, EndLoc, VL.size()); - Clause->setVarRefs(VL); +void OMPUseDevicePtrClause::setPrivateCopies(ArrayRef<Expr *> VL) { + assert(VL.size() == varlist_size() && + "Number of private copies is not the same as the preallocated buffer"); + std::copy(VL.begin(), VL.end(), varlist_end()); +} + +void OMPUseDevicePtrClause::setInits(ArrayRef<Expr *> VL) { + assert(VL.size() == varlist_size() && + "Number of inits is not the same as the preallocated buffer"); + std::copy(VL.begin(), VL.end(), getPrivateCopies().end()); +} + +OMPUseDevicePtrClause *OMPUseDevicePtrClause::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> Vars, ArrayRef<Expr *> PrivateVars, + ArrayRef<Expr *> Inits, ArrayRef<ValueDecl *> Declarations, + MappableExprComponentListsRef ComponentLists) { + unsigned NumVars = Vars.size(); + unsigned NumUniqueDeclarations = + getUniqueDeclarationsTotalNumber(Declarations); + unsigned NumComponentLists = ComponentLists.size(); + unsigned NumComponents = getComponentsTotalNumber(ComponentLists); + + // We need to allocate: + // 3 x NumVars x Expr* - we have an original list expression for each clause + // list entry and an equal number of private copies and inits. + // NumUniqueDeclarations x ValueDecl* - unique base declarations associated + // with each component list. + // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the + // number of lists for each unique declaration and the size of each component + // list. + // NumComponents x MappableComponent - the total of all the components in all + // the lists. + void *Mem = C.Allocate( + totalSizeToAlloc<Expr *, ValueDecl *, unsigned, + OMPClauseMappableExprCommon::MappableComponent>( + 3 * NumVars, NumUniqueDeclarations, + NumUniqueDeclarations + NumComponentLists, NumComponents)); + + OMPUseDevicePtrClause *Clause = new (Mem) OMPUseDevicePtrClause( + StartLoc, LParenLoc, EndLoc, NumVars, NumUniqueDeclarations, + NumComponentLists, NumComponents); + + Clause->setVarRefs(Vars); + Clause->setPrivateCopies(PrivateVars); + Clause->setInits(Inits); + Clause->setClauseInfo(Declarations, ComponentLists); return Clause; } -OMPUseDevicePtrClause *OMPUseDevicePtrClause::CreateEmpty(const ASTContext &C, - unsigned N) { - void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N)); - return new (Mem) OMPUseDevicePtrClause(N); +OMPUseDevicePtrClause *OMPUseDevicePtrClause::CreateEmpty( + const ASTContext &C, unsigned NumVars, unsigned NumUniqueDeclarations, + unsigned NumComponentLists, unsigned NumComponents) { + void *Mem = C.Allocate( + totalSizeToAlloc<Expr *, ValueDecl *, unsigned, + OMPClauseMappableExprCommon::MappableComponent>( + 3 * NumVars, NumUniqueDeclarations, + NumUniqueDeclarations + NumComponentLists, NumComponents)); + return new (Mem) OMPUseDevicePtrClause(NumVars, NumUniqueDeclarations, + NumComponentLists, NumComponents); } -OMPIsDevicePtrClause *OMPIsDevicePtrClause::Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc, - ArrayRef<Expr *> VL) { - void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size())); - OMPIsDevicePtrClause *Clause = - new (Mem) OMPIsDevicePtrClause(StartLoc, LParenLoc, EndLoc, VL.size()); - Clause->setVarRefs(VL); +OMPIsDevicePtrClause * +OMPIsDevicePtrClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + ArrayRef<Expr *> Vars, + ArrayRef<ValueDecl *> Declarations, + MappableExprComponentListsRef ComponentLists) { + unsigned NumVars = Vars.size(); + unsigned NumUniqueDeclarations = + getUniqueDeclarationsTotalNumber(Declarations); + unsigned NumComponentLists = ComponentLists.size(); + unsigned NumComponents = getComponentsTotalNumber(ComponentLists); + + // We need to allocate: + // NumVars x Expr* - we have an original list expression for each clause list + // entry. + // NumUniqueDeclarations x ValueDecl* - unique base declarations associated + // with each component list. + // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the + // number of lists for each unique declaration and the size of each component + // list. + // NumComponents x MappableComponent - the total of all the components in all + // the lists. + void *Mem = C.Allocate( + totalSizeToAlloc<Expr *, ValueDecl *, unsigned, + OMPClauseMappableExprCommon::MappableComponent>( + NumVars, NumUniqueDeclarations, + NumUniqueDeclarations + NumComponentLists, NumComponents)); + + OMPIsDevicePtrClause *Clause = new (Mem) OMPIsDevicePtrClause( + StartLoc, LParenLoc, EndLoc, NumVars, NumUniqueDeclarations, + NumComponentLists, NumComponents); + + Clause->setVarRefs(Vars); + Clause->setClauseInfo(Declarations, ComponentLists); return Clause; } -OMPIsDevicePtrClause *OMPIsDevicePtrClause::CreateEmpty(const ASTContext &C, - unsigned N) { - void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N)); - return new (Mem) OMPIsDevicePtrClause(N); +OMPIsDevicePtrClause *OMPIsDevicePtrClause::CreateEmpty( + const ASTContext &C, unsigned NumVars, unsigned NumUniqueDeclarations, + unsigned NumComponentLists, unsigned NumComponents) { + void *Mem = C.Allocate( + totalSizeToAlloc<Expr *, ValueDecl *, unsigned, + OMPClauseMappableExprCommon::MappableComponent>( + NumVars, NumUniqueDeclarations, + NumUniqueDeclarations + NumComponentLists, NumComponents)); + return new (Mem) OMPIsDevicePtrClause(NumVars, NumUniqueDeclarations, + NumComponentLists, NumComponents); } diff --git a/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp b/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp index 8317f76..881a7d9 100644 --- a/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp +++ b/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp @@ -175,8 +175,8 @@ StringRef RawComment::getRawTextSlow(const SourceManager &SourceMgr) const { } const char *RawComment::extractBriefText(const ASTContext &Context) const { - // Make sure that RawText is valid. - getRawText(Context.getSourceManager()); + // Lazily initialize RawText using the accessor before using it. + (void)getRawText(Context.getSourceManager()); // Since we will be copying the resulting text, all allocations made during // parsing are garbage after resulting string is formed. Thus we can use @@ -202,8 +202,8 @@ const char *RawComment::extractBriefText(const ASTContext &Context) const { comments::FullComment *RawComment::parse(const ASTContext &Context, const Preprocessor *PP, const Decl *D) const { - // Make sure that RawText is valid. - getRawText(Context.getSourceManager()); + // Lazily initialize RawText using the accessor before using it. + (void)getRawText(Context.getSourceManager()); comments::Lexer L(Context.getAllocator(), Context.getDiagnostics(), Context.getCommentCommandTraits(), @@ -334,4 +334,3 @@ void RawCommentList::addDeserializedComments(ArrayRef<RawComment *> Deserialized BeforeThanCompare<RawComment>(SourceMgr)); std::swap(Comments, MergedComments); } - diff --git a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp index 75c0763..697cdc3 100644 --- a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp @@ -315,7 +315,7 @@ AttributedStmt *AttributedStmt::Create(const ASTContext &C, SourceLocation Loc, Stmt *SubStmt) { assert(!Attrs.empty() && "Attrs should not be empty"); void *Mem = C.Allocate(sizeof(AttributedStmt) + sizeof(Attr *) * Attrs.size(), - llvm::alignOf<AttributedStmt>()); + alignof(AttributedStmt)); return new (Mem) AttributedStmt(Loc, Attrs, SubStmt); } @@ -323,7 +323,7 @@ AttributedStmt *AttributedStmt::CreateEmpty(const ASTContext &C, unsigned NumAttrs) { assert(NumAttrs > 0 && "NumAttrs should be greater than zero"); void *Mem = C.Allocate(sizeof(AttributedStmt) + sizeof(Attr *) * NumAttrs, - llvm::alignOf<AttributedStmt>()); + alignof(AttributedStmt)); return new (Mem) AttributedStmt(EmptyShell(), NumAttrs); } @@ -533,15 +533,17 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces, DiagOffs = CurPtr-StrStart-1; return diag::err_asm_invalid_escape; } - + // Handle escaped char and continue looping over the asm string. char EscapedChar = *CurPtr++; - if (EscapedChar == '%') { // %% -> % - // Escaped percentage sign. - CurStringPiece += '%'; + switch (EscapedChar) { + default: + break; + case '%': // %% -> % + case '{': // %{ -> { + case '}': // %} -> } + CurStringPiece += EscapedChar; continue; - } - - if (EscapedChar == '=') { // %= -> Generate an unique ID. + case '=': // %= -> Generate a unique ID. CurStringPiece += "${:uid}"; continue; } @@ -794,6 +796,10 @@ void IfStmt::setConditionVariable(const ASTContext &C, VarDecl *V) { VarRange.getEnd()); } +bool IfStmt::isObjCAvailabilityCheck() const { + return isa<ObjCAvailabilityCheckExpr>(SubExprs[COND]); +} + ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP, SourceLocation RP) @@ -998,7 +1004,7 @@ CapturedStmt::Capture *CapturedStmt::getStoredCaptures() const { unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1); // Offset of the first Capture object. - unsigned FirstCaptureOffset = llvm::alignTo(Size, llvm::alignOf<Capture>()); + unsigned FirstCaptureOffset = llvm::alignTo(Size, alignof(Capture)); return reinterpret_cast<Capture *>( reinterpret_cast<char *>(const_cast<CapturedStmt *>(this)) @@ -1055,7 +1061,7 @@ CapturedStmt *CapturedStmt::Create(const ASTContext &Context, Stmt *S, unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (Captures.size() + 1); if (!Captures.empty()) { // Realign for the following Capture array. - Size = llvm::alignTo(Size, llvm::alignOf<Capture>()); + Size = llvm::alignTo(Size, alignof(Capture)); Size += sizeof(Capture) * Captures.size(); } @@ -1068,7 +1074,7 @@ CapturedStmt *CapturedStmt::CreateDeserialized(const ASTContext &Context, unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1); if (NumCaptures > 0) { // Realign for the following Capture array. - Size = llvm::alignTo(Size, llvm::alignOf<Capture>()); + Size = llvm::alignTo(Size, alignof(Capture)); Size += sizeof(Capture) * NumCaptures; } diff --git a/contrib/llvm/tools/clang/lib/AST/StmtCXX.cpp b/contrib/llvm/tools/clang/lib/AST/StmtCXX.cpp index 4692db8..4a04fc2 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtCXX.cpp @@ -28,7 +28,7 @@ CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, SourceLocation tryLoc, std::size_t Size = sizeof(CXXTryStmt); Size += ((handlers.size() + 1) * sizeof(Stmt *)); - void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>()); + void *Mem = C.Allocate(Size, alignof(CXXTryStmt)); return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers); } @@ -37,7 +37,7 @@ CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, EmptyShell Empty, std::size_t Size = sizeof(CXXTryStmt); Size += ((numHandlers + 1) * sizeof(Stmt *)); - void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>()); + void *Mem = C.Allocate(Size, alignof(CXXTryStmt)); return new (Mem) CXXTryStmt(Empty, numHandlers); } diff --git a/contrib/llvm/tools/clang/lib/AST/StmtObjC.cpp b/contrib/llvm/tools/clang/lib/AST/StmtObjC.cpp index a77550c..eea03f6 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtObjC.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtObjC.cpp @@ -50,7 +50,7 @@ ObjCAtTryStmt *ObjCAtTryStmt::Create(const ASTContext &Context, unsigned Size = sizeof(ObjCAtTryStmt) + (1 + NumCatchStmts + (atFinallyStmt != nullptr)) * sizeof(Stmt *); - void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>()); + void *Mem = Context.Allocate(Size, alignof(ObjCAtTryStmt)); return new (Mem) ObjCAtTryStmt(atTryLoc, atTryStmt, CatchStmts, NumCatchStmts, atFinallyStmt); } @@ -60,7 +60,7 @@ ObjCAtTryStmt *ObjCAtTryStmt::CreateEmpty(const ASTContext &Context, bool HasFinally) { unsigned Size = sizeof(ObjCAtTryStmt) + (1 + NumCatchStmts + HasFinally) * sizeof(Stmt *); - void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>()); + void *Mem = Context.Allocate(Size, alignof(ObjCAtTryStmt)); return new (Mem) ObjCAtTryStmt(EmptyShell(), NumCatchStmts, HasFinally); } diff --git a/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp b/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp index f1ddedb..880817a 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp @@ -58,7 +58,7 @@ OMPParallelDirective *OMPParallelDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) { unsigned Size = - llvm::alignTo(sizeof(OMPParallelDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPParallelDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPParallelDirective *Dir = @@ -73,7 +73,7 @@ OMPParallelDirective *OMPParallelDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPParallelDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPParallelDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPParallelDirective(NumClauses); @@ -84,8 +84,7 @@ OMPSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs) { - unsigned Size = - llvm::alignTo(sizeof(OMPSimdDirective), llvm::alignOf<OMPClause *>()); + unsigned Size = llvm::alignTo(sizeof(OMPSimdDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd)); @@ -113,8 +112,7 @@ OMPSimdDirective *OMPSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = - llvm::alignTo(sizeof(OMPSimdDirective), llvm::alignOf<OMPClause *>()); + unsigned Size = llvm::alignTo(sizeof(OMPSimdDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd)); @@ -126,8 +124,7 @@ OMPForDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel) { - unsigned Size = - llvm::alignTo(sizeof(OMPForDirective), llvm::alignOf<OMPClause *>()); + unsigned Size = llvm::alignTo(sizeof(OMPForDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for)); @@ -166,8 +163,7 @@ OMPForDirective *OMPForDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = - llvm::alignTo(sizeof(OMPForDirective), llvm::alignOf<OMPClause *>()); + unsigned Size = llvm::alignTo(sizeof(OMPForDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for)); @@ -180,7 +176,7 @@ OMPForSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs) { unsigned Size = - llvm::alignTo(sizeof(OMPForSimdDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPForSimdDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd)); @@ -219,7 +215,7 @@ OMPForSimdDirective *OMPForSimdDirective::CreateEmpty(const ASTContext &C, unsigned CollapsedNum, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPForSimdDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPForSimdDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd)); @@ -230,7 +226,7 @@ OMPSectionsDirective *OMPSectionsDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) { unsigned Size = - llvm::alignTo(sizeof(OMPSectionsDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPSectionsDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPSectionsDirective *Dir = @@ -245,7 +241,7 @@ OMPSectionsDirective *OMPSectionsDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPSectionsDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPSectionsDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPSectionsDirective(NumClauses); @@ -256,8 +252,7 @@ OMPSectionDirective *OMPSectionDirective::Create(const ASTContext &C, SourceLocation EndLoc, Stmt *AssociatedStmt, bool HasCancel) { - unsigned Size = - llvm::alignTo(sizeof(OMPSectionDirective), llvm::alignOf<Stmt *>()); + unsigned Size = llvm::alignTo(sizeof(OMPSectionDirective), alignof(Stmt *)); void *Mem = C.Allocate(Size + sizeof(Stmt *)); OMPSectionDirective *Dir = new (Mem) OMPSectionDirective(StartLoc, EndLoc); Dir->setAssociatedStmt(AssociatedStmt); @@ -267,8 +262,7 @@ OMPSectionDirective *OMPSectionDirective::Create(const ASTContext &C, OMPSectionDirective *OMPSectionDirective::CreateEmpty(const ASTContext &C, EmptyShell) { - unsigned Size = - llvm::alignTo(sizeof(OMPSectionDirective), llvm::alignOf<Stmt *>()); + unsigned Size = llvm::alignTo(sizeof(OMPSectionDirective), alignof(Stmt *)); void *Mem = C.Allocate(Size + sizeof(Stmt *)); return new (Mem) OMPSectionDirective(); } @@ -279,7 +273,7 @@ OMPSingleDirective *OMPSingleDirective::Create(const ASTContext &C, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { unsigned Size = - llvm::alignTo(sizeof(OMPSingleDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPSingleDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPSingleDirective *Dir = @@ -293,7 +287,7 @@ OMPSingleDirective *OMPSingleDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPSingleDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPSingleDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPSingleDirective(NumClauses); @@ -303,8 +297,7 @@ OMPMasterDirective *OMPMasterDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt) { - unsigned Size = - llvm::alignTo(sizeof(OMPMasterDirective), llvm::alignOf<Stmt *>()); + unsigned Size = llvm::alignTo(sizeof(OMPMasterDirective), alignof(Stmt *)); void *Mem = C.Allocate(Size + sizeof(Stmt *)); OMPMasterDirective *Dir = new (Mem) OMPMasterDirective(StartLoc, EndLoc); Dir->setAssociatedStmt(AssociatedStmt); @@ -313,8 +306,7 @@ OMPMasterDirective *OMPMasterDirective::Create(const ASTContext &C, OMPMasterDirective *OMPMasterDirective::CreateEmpty(const ASTContext &C, EmptyShell) { - unsigned Size = - llvm::alignTo(sizeof(OMPMasterDirective), llvm::alignOf<Stmt *>()); + unsigned Size = llvm::alignTo(sizeof(OMPMasterDirective), alignof(Stmt *)); void *Mem = C.Allocate(Size + sizeof(Stmt *)); return new (Mem) OMPMasterDirective(); } @@ -324,7 +316,7 @@ OMPCriticalDirective *OMPCriticalDirective::Create( SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { unsigned Size = - llvm::alignTo(sizeof(OMPCriticalDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPCriticalDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPCriticalDirective *Dir = @@ -338,7 +330,7 @@ OMPCriticalDirective *OMPCriticalDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPCriticalDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPCriticalDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPCriticalDirective(NumClauses); @@ -348,8 +340,8 @@ OMPParallelForDirective *OMPParallelForDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel) { - unsigned Size = llvm::alignTo(sizeof(OMPParallelForDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPParallelForDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for)); @@ -387,8 +379,8 @@ OMPParallelForDirective *OMPParallelForDirective::Create( OMPParallelForDirective * OMPParallelForDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = llvm::alignTo(sizeof(OMPParallelForDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPParallelForDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for)); @@ -399,8 +391,8 @@ OMPParallelForSimdDirective *OMPParallelForSimdDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs) { - unsigned Size = llvm::alignTo(sizeof(OMPParallelForSimdDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPParallelForSimdDirective), alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd)); @@ -438,8 +430,8 @@ OMPParallelForSimdDirective * OMPParallelForSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = llvm::alignTo(sizeof(OMPParallelForSimdDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPParallelForSimdDirective), alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd)); @@ -449,8 +441,8 @@ OMPParallelForSimdDirective::CreateEmpty(const ASTContext &C, OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) { - unsigned Size = llvm::alignTo(sizeof(OMPParallelSectionsDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPParallelSectionsDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPParallelSectionsDirective *Dir = @@ -464,8 +456,8 @@ OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create( OMPParallelSectionsDirective * OMPParallelSectionsDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { - unsigned Size = llvm::alignTo(sizeof(OMPParallelSectionsDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPParallelSectionsDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPParallelSectionsDirective(NumClauses); @@ -475,8 +467,7 @@ OMPTaskDirective * OMPTaskDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) { - unsigned Size = - llvm::alignTo(sizeof(OMPTaskDirective), llvm::alignOf<OMPClause *>()); + unsigned Size = llvm::alignTo(sizeof(OMPTaskDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPTaskDirective *Dir = @@ -490,8 +481,7 @@ OMPTaskDirective::Create(const ASTContext &C, SourceLocation StartLoc, OMPTaskDirective *OMPTaskDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { - unsigned Size = - llvm::alignTo(sizeof(OMPTaskDirective), llvm::alignOf<OMPClause *>()); + unsigned Size = llvm::alignTo(sizeof(OMPTaskDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPTaskDirective(NumClauses); @@ -544,8 +534,7 @@ OMPTaskgroupDirective *OMPTaskgroupDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt) { - unsigned Size = - llvm::alignTo(sizeof(OMPTaskgroupDirective), llvm::alignOf<Stmt *>()); + unsigned Size = llvm::alignTo(sizeof(OMPTaskgroupDirective), alignof(Stmt *)); void *Mem = C.Allocate(Size + sizeof(Stmt *)); OMPTaskgroupDirective *Dir = new (Mem) OMPTaskgroupDirective(StartLoc, EndLoc); @@ -555,8 +544,7 @@ OMPTaskgroupDirective *OMPTaskgroupDirective::Create(const ASTContext &C, OMPTaskgroupDirective *OMPTaskgroupDirective::CreateEmpty(const ASTContext &C, EmptyShell) { - unsigned Size = - llvm::alignTo(sizeof(OMPTaskgroupDirective), llvm::alignOf<Stmt *>()); + unsigned Size = llvm::alignTo(sizeof(OMPTaskgroupDirective), alignof(Stmt *)); void *Mem = C.Allocate(Size + sizeof(Stmt *)); return new (Mem) OMPTaskgroupDirective(); } @@ -564,8 +552,8 @@ OMPTaskgroupDirective *OMPTaskgroupDirective::CreateEmpty(const ASTContext &C, OMPCancellationPointDirective *OMPCancellationPointDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) { - unsigned Size = llvm::alignTo(sizeof(OMPCancellationPointDirective), - llvm::alignOf<Stmt *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPCancellationPointDirective), alignof(Stmt *)); void *Mem = C.Allocate(Size); OMPCancellationPointDirective *Dir = new (Mem) OMPCancellationPointDirective(StartLoc, EndLoc); @@ -575,8 +563,8 @@ OMPCancellationPointDirective *OMPCancellationPointDirective::Create( OMPCancellationPointDirective * OMPCancellationPointDirective::CreateEmpty(const ASTContext &C, EmptyShell) { - unsigned Size = llvm::alignTo(sizeof(OMPCancellationPointDirective), - llvm::alignOf<Stmt *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPCancellationPointDirective), alignof(Stmt *)); void *Mem = C.Allocate(Size); return new (Mem) OMPCancellationPointDirective(); } @@ -587,7 +575,7 @@ OMPCancelDirective::Create(const ASTContext &C, SourceLocation StartLoc, OpenMPDirectiveKind CancelRegion) { unsigned Size = llvm::alignTo(sizeof(OMPCancelDirective) + sizeof(OMPClause *) * Clauses.size(), - llvm::alignOf<Stmt *>()); + alignof(Stmt *)); void *Mem = C.Allocate(Size); OMPCancelDirective *Dir = new (Mem) OMPCancelDirective(StartLoc, EndLoc, Clauses.size()); @@ -601,7 +589,7 @@ OMPCancelDirective *OMPCancelDirective::CreateEmpty(const ASTContext &C, EmptyShell) { unsigned Size = llvm::alignTo(sizeof(OMPCancelDirective) + sizeof(OMPClause *) * NumClauses, - llvm::alignOf<Stmt *>()); + alignof(Stmt *)); void *Mem = C.Allocate(Size); return new (Mem) OMPCancelDirective(NumClauses); } @@ -611,7 +599,7 @@ OMPFlushDirective *OMPFlushDirective::Create(const ASTContext &C, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses) { unsigned Size = - llvm::alignTo(sizeof(OMPFlushDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPFlushDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size()); OMPFlushDirective *Dir = new (Mem) OMPFlushDirective(StartLoc, EndLoc, Clauses.size()); @@ -623,7 +611,7 @@ OMPFlushDirective *OMPFlushDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPFlushDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPFlushDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses); return new (Mem) OMPFlushDirective(NumClauses); } @@ -634,7 +622,7 @@ OMPOrderedDirective *OMPOrderedDirective::Create(const ASTContext &C, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { unsigned Size = - llvm::alignTo(sizeof(OMPOrderedDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPOrderedDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(Stmt *) + sizeof(OMPClause *) * Clauses.size()); OMPOrderedDirective *Dir = @@ -648,7 +636,7 @@ OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPOrderedDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPOrderedDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(Stmt *) + sizeof(OMPClause *) * NumClauses); return new (Mem) OMPOrderedDirective(NumClauses); @@ -659,7 +647,7 @@ OMPAtomicDirective *OMPAtomicDirective::Create( ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V, Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate) { unsigned Size = - llvm::alignTo(sizeof(OMPAtomicDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPAtomicDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + 5 * sizeof(Stmt *)); OMPAtomicDirective *Dir = @@ -679,7 +667,7 @@ OMPAtomicDirective *OMPAtomicDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPAtomicDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPAtomicDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + 5 * sizeof(Stmt *)); return new (Mem) OMPAtomicDirective(NumClauses); @@ -691,7 +679,7 @@ OMPTargetDirective *OMPTargetDirective::Create(const ASTContext &C, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { unsigned Size = - llvm::alignTo(sizeof(OMPTargetDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPTargetDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPTargetDirective *Dir = @@ -705,7 +693,7 @@ OMPTargetDirective *OMPTargetDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPTargetDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPTargetDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPTargetDirective(NumClauses); @@ -714,8 +702,8 @@ OMPTargetDirective *OMPTargetDirective::CreateEmpty(const ASTContext &C, OMPTargetParallelDirective *OMPTargetParallelDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { - unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTargetParallelDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPTargetParallelDirective *Dir = @@ -728,8 +716,8 @@ OMPTargetParallelDirective *OMPTargetParallelDirective::Create( OMPTargetParallelDirective * OMPTargetParallelDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { - unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTargetParallelDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPTargetParallelDirective(NumClauses); @@ -740,7 +728,7 @@ OMPTargetParallelForDirective *OMPTargetParallelForDirective::Create( unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel) { unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForDirective), - llvm::alignOf<OMPClause *>()); + alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_target_parallel_for)); @@ -780,7 +768,7 @@ OMPTargetParallelForDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForDirective), - llvm::alignOf<OMPClause *>()); + alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_target_parallel_for)); @@ -790,9 +778,9 @@ OMPTargetParallelForDirective::CreateEmpty(const ASTContext &C, OMPTargetDataDirective *OMPTargetDataDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { - void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetDataDirective), - llvm::alignOf<OMPClause *>()) + - sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + void *Mem = C.Allocate( + llvm::alignTo(sizeof(OMPTargetDataDirective), alignof(OMPClause *)) + + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPTargetDataDirective *Dir = new (Mem) OMPTargetDataDirective(StartLoc, EndLoc, Clauses.size()); Dir->setClauses(Clauses); @@ -803,18 +791,18 @@ OMPTargetDataDirective *OMPTargetDataDirective::Create( OMPTargetDataDirective *OMPTargetDataDirective::CreateEmpty(const ASTContext &C, unsigned N, EmptyShell) { - void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetDataDirective), - llvm::alignOf<OMPClause *>()) + - sizeof(OMPClause *) * N + sizeof(Stmt *)); + void *Mem = C.Allocate( + llvm::alignTo(sizeof(OMPTargetDataDirective), alignof(OMPClause *)) + + sizeof(OMPClause *) * N + sizeof(Stmt *)); return new (Mem) OMPTargetDataDirective(N); } OMPTargetEnterDataDirective *OMPTargetEnterDataDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses) { - void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetEnterDataDirective), - llvm::alignOf<OMPClause *>()) + - sizeof(OMPClause *) * Clauses.size()); + void *Mem = C.Allocate( + llvm::alignTo(sizeof(OMPTargetEnterDataDirective), alignof(OMPClause *)) + + sizeof(OMPClause *) * Clauses.size()); OMPTargetEnterDataDirective *Dir = new (Mem) OMPTargetEnterDataDirective(StartLoc, EndLoc, Clauses.size()); Dir->setClauses(Clauses); @@ -824,9 +812,9 @@ OMPTargetEnterDataDirective *OMPTargetEnterDataDirective::Create( OMPTargetEnterDataDirective * OMPTargetEnterDataDirective::CreateEmpty(const ASTContext &C, unsigned N, EmptyShell) { - void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetEnterDataDirective), - llvm::alignOf<OMPClause *>()) + - sizeof(OMPClause *) * N); + void *Mem = C.Allocate( + llvm::alignTo(sizeof(OMPTargetEnterDataDirective), alignof(OMPClause *)) + + sizeof(OMPClause *) * N); return new (Mem) OMPTargetEnterDataDirective(N); } @@ -834,9 +822,9 @@ OMPTargetExitDataDirective * OMPTargetExitDataDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses) { - void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetExitDataDirective), - llvm::alignOf<OMPClause *>()) + - sizeof(OMPClause *) * Clauses.size()); + void *Mem = C.Allocate( + llvm::alignTo(sizeof(OMPTargetExitDataDirective), alignof(OMPClause *)) + + sizeof(OMPClause *) * Clauses.size()); OMPTargetExitDataDirective *Dir = new (Mem) OMPTargetExitDataDirective(StartLoc, EndLoc, Clauses.size()); Dir->setClauses(Clauses); @@ -846,9 +834,9 @@ OMPTargetExitDataDirective::Create(const ASTContext &C, SourceLocation StartLoc, OMPTargetExitDataDirective * OMPTargetExitDataDirective::CreateEmpty(const ASTContext &C, unsigned N, EmptyShell) { - void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetExitDataDirective), - llvm::alignOf<OMPClause *>()) + - sizeof(OMPClause *) * N); + void *Mem = C.Allocate( + llvm::alignTo(sizeof(OMPTargetExitDataDirective), alignof(OMPClause *)) + + sizeof(OMPClause *) * N); return new (Mem) OMPTargetExitDataDirective(N); } @@ -858,7 +846,7 @@ OMPTeamsDirective *OMPTeamsDirective::Create(const ASTContext &C, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { unsigned Size = - llvm::alignTo(sizeof(OMPTeamsDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPTeamsDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPTeamsDirective *Dir = @@ -872,7 +860,7 @@ OMPTeamsDirective *OMPTeamsDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPTeamsDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPTeamsDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPTeamsDirective(NumClauses); @@ -883,7 +871,7 @@ OMPTaskLoopDirective *OMPTaskLoopDirective::Create( unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs) { unsigned Size = - llvm::alignTo(sizeof(OMPTaskLoopDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPTaskLoopDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop)); @@ -922,7 +910,7 @@ OMPTaskLoopDirective *OMPTaskLoopDirective::CreateEmpty(const ASTContext &C, unsigned CollapsedNum, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPTaskLoopDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPTaskLoopDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop)); @@ -933,8 +921,8 @@ OMPTaskLoopSimdDirective *OMPTaskLoopSimdDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs) { - unsigned Size = llvm::alignTo(sizeof(OMPTaskLoopSimdDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTaskLoopSimdDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop_simd)); @@ -971,8 +959,8 @@ OMPTaskLoopSimdDirective *OMPTaskLoopSimdDirective::Create( OMPTaskLoopSimdDirective * OMPTaskLoopSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = llvm::alignTo(sizeof(OMPTaskLoopSimdDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTaskLoopSimdDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop_simd)); @@ -983,8 +971,8 @@ OMPDistributeDirective *OMPDistributeDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs) { - unsigned Size = llvm::alignTo(sizeof(OMPDistributeDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPDistributeDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_distribute)); @@ -1021,8 +1009,8 @@ OMPDistributeDirective *OMPDistributeDirective::Create( OMPDistributeDirective * OMPDistributeDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = llvm::alignTo(sizeof(OMPDistributeDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPDistributeDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_distribute)); @@ -1033,8 +1021,8 @@ OMPTargetUpdateDirective * OMPTargetUpdateDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses) { - unsigned Size = llvm::alignTo(sizeof(OMPTargetUpdateDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTargetUpdateDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size()); OMPTargetUpdateDirective *Dir = new (Mem) OMPTargetUpdateDirective(StartLoc, EndLoc, Clauses.size()); @@ -1045,8 +1033,8 @@ OMPTargetUpdateDirective::Create(const ASTContext &C, SourceLocation StartLoc, OMPTargetUpdateDirective * OMPTargetUpdateDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { - unsigned Size = llvm::alignTo(sizeof(OMPTargetUpdateDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTargetUpdateDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses); return new (Mem) OMPTargetUpdateDirective(NumClauses); } @@ -1056,7 +1044,7 @@ OMPDistributeParallelForDirective *OMPDistributeParallelForDirective::Create( unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs) { unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForDirective), - llvm::alignOf<OMPClause *>()); + alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * @@ -1098,7 +1086,7 @@ OMPDistributeParallelForDirective::CreateEmpty(const ASTContext &C, unsigned CollapsedNum, EmptyShell) { unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForDirective), - llvm::alignOf<OMPClause *>()); + alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * @@ -1112,7 +1100,7 @@ OMPDistributeParallelForSimdDirective::Create( unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs) { unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForSimdDirective), - llvm::alignOf<OMPClause *>()); + alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * @@ -1154,7 +1142,7 @@ OMPDistributeParallelForSimdDirective::CreateEmpty(const ASTContext &C, unsigned CollapsedNum, EmptyShell) { unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForSimdDirective), - llvm::alignOf<OMPClause *>()); + alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * @@ -1167,8 +1155,8 @@ OMPDistributeSimdDirective *OMPDistributeSimdDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs) { - unsigned Size = llvm::alignTo(sizeof(OMPDistributeSimdDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPDistributeSimdDirective), alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * @@ -1207,8 +1195,8 @@ OMPDistributeSimdDirective * OMPDistributeSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = llvm::alignTo(sizeof(OMPDistributeSimdDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPDistributeSimdDirective), alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * @@ -1221,7 +1209,7 @@ OMPTargetParallelForSimdDirective *OMPTargetParallelForSimdDirective::Create( unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs) { unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForSimdDirective), - llvm::alignOf<OMPClause *>()); + alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * @@ -1263,10 +1251,528 @@ OMPTargetParallelForSimdDirective::CreateEmpty(const ASTContext &C, unsigned CollapsedNum, EmptyShell) { unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForSimdDirective), - llvm::alignOf<OMPClause *>()); + alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_target_parallel_for_simd)); return new (Mem) OMPTargetParallelForSimdDirective(CollapsedNum, NumClauses); } + +OMPTargetSimdDirective * +OMPTargetSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, unsigned CollapsedNum, + ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs) { + unsigned Size = + llvm::alignTo(sizeof(OMPTargetSimdDirective), alignof(OMPClause *)); + void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_target_simd)); + OMPTargetSimdDirective *Dir = new (Mem) + OMPTargetSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPTargetSimdDirective * +OMPTargetSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, + unsigned CollapsedNum, EmptyShell) { + unsigned Size = + llvm::alignTo(sizeof(OMPTargetSimdDirective), alignof(OMPClause *)); + void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_target_simd)); + return new (Mem) OMPTargetSimdDirective(CollapsedNum, NumClauses); +} + +OMPTeamsDistributeDirective *OMPTeamsDistributeDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + unsigned Size = + llvm::alignTo(sizeof(OMPTeamsDistributeDirective), alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_teams_distribute)); + OMPTeamsDistributeDirective *Dir = new (Mem) OMPTeamsDistributeDirective( + StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPTeamsDistributeDirective * +OMPTeamsDistributeDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, EmptyShell) { + unsigned Size = + llvm::alignTo(sizeof(OMPTeamsDistributeDirective), alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_teams_distribute)); + return new (Mem) OMPTeamsDistributeDirective(CollapsedNum, NumClauses); +} + +OMPTeamsDistributeSimdDirective *OMPTeamsDistributeSimdDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + unsigned Size = llvm::alignTo(sizeof(OMPTeamsDistributeSimdDirective), + alignof(OMPClause *)); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_teams_distribute_simd)); + OMPTeamsDistributeSimdDirective *Dir = + new (Mem) OMPTeamsDistributeSimdDirective(StartLoc, EndLoc, CollapsedNum, + Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPTeamsDistributeSimdDirective *OMPTeamsDistributeSimdDirective::CreateEmpty( + const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, + EmptyShell) { + unsigned Size = llvm::alignTo(sizeof(OMPTeamsDistributeSimdDirective), + alignof(OMPClause *)); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_teams_distribute_simd)); + return new (Mem) OMPTeamsDistributeSimdDirective(CollapsedNum, NumClauses); +} + +OMPTeamsDistributeParallelForSimdDirective * +OMPTeamsDistributeParallelForSimdDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForSimdDirective), + alignof(OMPClause *)); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, + OMPD_teams_distribute_parallel_for_simd)); + OMPTeamsDistributeParallelForSimdDirective *Dir = new (Mem) + OMPTeamsDistributeParallelForSimdDirective(StartLoc, EndLoc, CollapsedNum, + Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPTeamsDistributeParallelForSimdDirective * +OMPTeamsDistributeParallelForSimdDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForSimdDirective), + alignof(OMPClause *)); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, + OMPD_teams_distribute_parallel_for_simd)); + return new (Mem) + OMPTeamsDistributeParallelForSimdDirective(CollapsedNum, NumClauses); +} + +OMPTeamsDistributeParallelForDirective * +OMPTeamsDistributeParallelForDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForDirective), + alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_teams_distribute_parallel_for)); + OMPTeamsDistributeParallelForDirective *Dir = new (Mem) + OMPTeamsDistributeParallelForDirective(StartLoc, EndLoc, CollapsedNum, + Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPTeamsDistributeParallelForDirective * +OMPTeamsDistributeParallelForDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForDirective), + alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_teams_distribute_parallel_for)); + return new (Mem) + OMPTeamsDistributeParallelForDirective(CollapsedNum, NumClauses); +} + +OMPTargetTeamsDirective *OMPTargetTeamsDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { + auto Size = + llvm::alignTo(sizeof(OMPTargetTeamsDirective), alignof(OMPClause *)); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + OMPTargetTeamsDirective *Dir = + new (Mem) OMPTargetTeamsDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPTargetTeamsDirective * +OMPTargetTeamsDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, + EmptyShell) { + auto Size = + llvm::alignTo(sizeof(OMPTargetTeamsDirective), alignof(OMPClause *)); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + return new (Mem) OMPTargetTeamsDirective(NumClauses); +} + +OMPTargetTeamsDistributeDirective *OMPTargetTeamsDistributeDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + auto Size = llvm::alignTo(sizeof(OMPTargetTeamsDistributeDirective), + alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_target_teams_distribute)); + OMPTargetTeamsDistributeDirective *Dir = + new (Mem) OMPTargetTeamsDistributeDirective(StartLoc, EndLoc, CollapsedNum, + Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPTargetTeamsDistributeDirective * +OMPTargetTeamsDistributeDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + auto Size = llvm::alignTo(sizeof(OMPTargetTeamsDistributeDirective), + alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_target_teams_distribute)); + return new (Mem) OMPTargetTeamsDistributeDirective(CollapsedNum, NumClauses); +} + +OMPTargetTeamsDistributeParallelForDirective * +OMPTargetTeamsDistributeParallelForDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + auto Size = + llvm::alignTo(sizeof(OMPTargetTeamsDistributeParallelForDirective), + alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, + OMPD_target_teams_distribute_parallel_for)); + OMPTargetTeamsDistributeParallelForDirective *Dir = + new (Mem) OMPTargetTeamsDistributeParallelForDirective( + StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPTargetTeamsDistributeParallelForDirective * +OMPTargetTeamsDistributeParallelForDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + auto Size = + llvm::alignTo(sizeof(OMPTargetTeamsDistributeParallelForDirective), + alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, + OMPD_target_teams_distribute_parallel_for)); + return new (Mem) + OMPTargetTeamsDistributeParallelForDirective(CollapsedNum, NumClauses); +} + +OMPTargetTeamsDistributeParallelForSimdDirective * +OMPTargetTeamsDistributeParallelForSimdDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + auto Size = + llvm::alignTo(sizeof(OMPTargetTeamsDistributeParallelForSimdDirective), + alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, + OMPD_target_teams_distribute_parallel_for_simd)); + OMPTargetTeamsDistributeParallelForSimdDirective *Dir = + new (Mem) OMPTargetTeamsDistributeParallelForSimdDirective( + StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPTargetTeamsDistributeParallelForSimdDirective * +OMPTargetTeamsDistributeParallelForSimdDirective::CreateEmpty( + const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, + EmptyShell) { + auto Size = + llvm::alignTo(sizeof(OMPTargetTeamsDistributeParallelForSimdDirective), + alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, + OMPD_target_teams_distribute_parallel_for_simd)); + return new (Mem) OMPTargetTeamsDistributeParallelForSimdDirective( + CollapsedNum, NumClauses); +} + +OMPTargetTeamsDistributeSimdDirective * +OMPTargetTeamsDistributeSimdDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + auto Size = llvm::alignTo(sizeof(OMPTargetTeamsDistributeSimdDirective), + alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_target_teams_distribute_simd)); + OMPTargetTeamsDistributeSimdDirective *Dir = new (Mem) + OMPTargetTeamsDistributeSimdDirective(StartLoc, EndLoc, CollapsedNum, + Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPTargetTeamsDistributeSimdDirective * +OMPTargetTeamsDistributeSimdDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + auto Size = llvm::alignTo(sizeof(OMPTargetTeamsDistributeSimdDirective), + alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_target_teams_distribute_simd)); + return new (Mem) + OMPTargetTeamsDistributeSimdDirective(CollapsedNum, NumClauses); +} diff --git a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp index 8797a13..1ba1aa4 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp @@ -1198,6 +1198,64 @@ void StmtPrinter::VisitOMPTargetParallelForSimdDirective( PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPTargetSimdDirective(OMPTargetSimdDirective *Node) { + Indent() << "#pragma omp target simd "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTeamsDistributeDirective( + OMPTeamsDistributeDirective *Node) { + Indent() << "#pragma omp teams distribute "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTeamsDistributeSimdDirective( + OMPTeamsDistributeSimdDirective *Node) { + Indent() << "#pragma omp teams distribute simd "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTeamsDistributeParallelForSimdDirective( + OMPTeamsDistributeParallelForSimdDirective *Node) { + Indent() << "#pragma omp teams distribute parallel for simd "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTeamsDistributeParallelForDirective( + OMPTeamsDistributeParallelForDirective *Node) { + Indent() << "#pragma omp teams distribute parallel for "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTargetTeamsDirective(OMPTargetTeamsDirective *Node) { + Indent() << "#pragma omp target teams "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTargetTeamsDistributeDirective( + OMPTargetTeamsDistributeDirective *Node) { + Indent() << "#pragma omp target teams distribute "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTargetTeamsDistributeParallelForDirective( + OMPTargetTeamsDistributeParallelForDirective *Node) { + Indent() << "#pragma omp target teams distribute parallel for "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTargetTeamsDistributeParallelForSimdDirective( + OMPTargetTeamsDistributeParallelForSimdDirective *Node) { + Indent() << "#pragma omp target teams distribute parallel for simd "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTargetTeamsDistributeSimdDirective( + OMPTargetTeamsDistributeSimdDirective *Node) { + Indent() << "#pragma omp target teams distribute simd "; + PrintOMPExecutableDirective(Node); +} + //===----------------------------------------------------------------------===// // Expr printing methods. //===----------------------------------------------------------------------===// @@ -1676,6 +1734,18 @@ void StmtPrinter::VisitInitListExpr(InitListExpr* Node) { OS << "}"; } +void StmtPrinter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *Node) { + // There's no way to express this expression in any of our supported + // languages, so just emit something terse and (hopefully) clear. + OS << "{"; + PrintExpr(Node->getSubExpr()); + OS << "}"; +} + +void StmtPrinter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *Node) { + OS << "*"; +} + void StmtPrinter::VisitParenListExpr(ParenListExpr* Node) { OS << "("; for (unsigned i = 0, e = Node->getNumExprs(); i != e; ++i) { diff --git a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp index 0a39413..bcd2e96 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp @@ -93,10 +93,6 @@ void StmtProfiler::VisitCompoundStmt(const CompoundStmt *S) { VisitStmt(S); } -void StmtProfiler::VisitSwitchCase(const SwitchCase *S) { - VisitStmt(S); -} - void StmtProfiler::VisitCaseStmt(const CaseStmt *S) { VisitStmt(S); } @@ -727,6 +723,56 @@ void StmtProfiler::VisitOMPTargetParallelForSimdDirective( VisitOMPLoopDirective(S); } +void StmtProfiler::VisitOMPTargetSimdDirective( + const OMPTargetSimdDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPTeamsDistributeDirective( + const OMPTeamsDistributeDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPTeamsDistributeSimdDirective( + const OMPTeamsDistributeSimdDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPTeamsDistributeParallelForSimdDirective( + const OMPTeamsDistributeParallelForSimdDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPTeamsDistributeParallelForDirective( + const OMPTeamsDistributeParallelForDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPTargetTeamsDirective( + const OMPTargetTeamsDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPTargetTeamsDistributeDirective( + const OMPTargetTeamsDistributeDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPTargetTeamsDistributeParallelForDirective( + const OMPTargetTeamsDistributeParallelForDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPTargetTeamsDistributeParallelForSimdDirective( + const OMPTargetTeamsDistributeParallelForSimdDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPTargetTeamsDistributeSimdDirective( + const OMPTargetTeamsDistributeSimdDirective *S) { + VisitOMPLoopDirective(S); +} + void StmtProfiler::VisitExpr(const Expr *S) { VisitStmt(S); } @@ -951,6 +997,14 @@ void StmtProfiler::VisitDesignatedInitUpdateExpr( "initializer"); } +void StmtProfiler::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *S) { + VisitExpr(S); +} + +void StmtProfiler::VisitArrayInitIndexExpr(const ArrayInitIndexExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitNoInitExpr(const NoInitExpr *S) { llvm_unreachable("Unexpected NoInitExpr in syntactic form of initializer"); } @@ -1184,6 +1238,12 @@ void StmtProfiler::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) { if (S->isTypeDependent()) { // Type-dependent operator calls are profiled like their underlying // syntactic operator. + // + // An operator call to operator-> is always implicit, so just skip it. The + // enclosing MemberExpr will profile the actual member access. + if (S->getOperator() == OO_Arrow) + return Visit(S->getArg(0)); + UnaryOperatorKind UnaryOp = UO_Extension; BinaryOperatorKind BinaryOp = BO_Comma; Stmt::StmtClass SC = DecodeOperatorCall(S, UnaryOp, BinaryOp); diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp index b75ede8..099f939 100644 --- a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp @@ -243,6 +243,31 @@ Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const { return None; } +QualType TemplateArgument::getNonTypeTemplateArgumentType() const { + switch (getKind()) { + case TemplateArgument::Null: + case TemplateArgument::Type: + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + case TemplateArgument::Pack: + return QualType(); + + case TemplateArgument::Integral: + return getIntegralType(); + + case TemplateArgument::Expression: + return getAsExpr()->getType(); + + case TemplateArgument::Declaration: + return getParamTypeForDecl(); + + case TemplateArgument::NullPtr: + return getNullPtrType(); + } + + llvm_unreachable("Invalid TemplateArgument Kind!"); +} + void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const { ID.AddInteger(getKind()); @@ -530,7 +555,7 @@ const ASTTemplateArgumentListInfo * ASTTemplateArgumentListInfo::Create(ASTContext &C, const TemplateArgumentListInfo &List) { std::size_t size = totalSizeToAlloc<TemplateArgumentLoc>(List.size()); - void *Mem = C.Allocate(size, llvm::alignOf<ASTTemplateArgumentListInfo>()); + void *Mem = C.Allocate(size, alignof(ASTTemplateArgumentListInfo)); return new (Mem) ASTTemplateArgumentListInfo(List); } diff --git a/contrib/llvm/tools/clang/lib/AST/Type.cpp b/contrib/llvm/tools/clang/lib/AST/Type.cpp index 99b0247..0d0cd2e 100644 --- a/contrib/llvm/tools/clang/lib/AST/Type.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Type.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/Type.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" #include "clang/AST/CharUnits.h" @@ -19,13 +20,11 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/PrettyPrinter.h" -#include "clang/AST/Type.h" #include "clang/AST/TypeVisitor.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/Support/raw_ostream.h" #include <algorithm> using namespace clang; @@ -532,6 +531,18 @@ bool Type::isObjCInertUnsafeUnretainedType() const { } } +ObjCTypeParamType::ObjCTypeParamType(const ObjCTypeParamDecl *D, + QualType can, + ArrayRef<ObjCProtocolDecl *> protocols) + : Type(ObjCTypeParam, can, can->isDependentType(), + can->isInstantiationDependentType(), + can->isVariablyModifiedType(), + /*ContainsUnexpandedParameterPack=*/false), + OTPDecl(const_cast<ObjCTypeParamDecl*>(D)) +{ + initialize(protocols); +} + ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base, ArrayRef<QualType> typeArgs, ArrayRef<ObjCProtocolDecl *> protocols, @@ -547,15 +558,9 @@ ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base, ObjCObjectTypeBits.NumTypeArgs = typeArgs.size(); assert(getTypeArgsAsWritten().size() == typeArgs.size() && "bitfield overflow in type argument count"); - ObjCObjectTypeBits.NumProtocols = protocols.size(); - assert(getNumProtocols() == protocols.size() && - "bitfield overflow in protocol count"); if (!typeArgs.empty()) memcpy(getTypeArgStorage(), typeArgs.data(), typeArgs.size() * sizeof(QualType)); - if (!protocols.empty()) - memcpy(getProtocolStorage(), protocols.data(), - protocols.size() * sizeof(ObjCProtocolDecl*)); for (auto typeArg : typeArgs) { if (typeArg->isDependentType()) @@ -566,6 +571,9 @@ ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base, if (typeArg->containsUnexpandedParameterPack()) setContainsUnexpandedParameterPack(); } + // Initialize the protocol qualifiers. The protocol storage is known + // after we set number of type arguments. + initialize(protocols); } bool ObjCObjectType::isSpecialized() const { @@ -883,6 +891,7 @@ public: } TRIVIAL_TYPE_CLASS(Typedef) + TRIVIAL_TYPE_CLASS(ObjCTypeParam) QualType VisitAdjustedType(const AdjustedType *T) { QualType originalType = recurse(T->getOriginalType()); @@ -1048,7 +1057,7 @@ QualType simpleTransform(ASTContext &ctx, QualType type, F &&f) { SplitQualType splitType = type.split(); // Visit the type itself. - SimpleTransformVisitor<F> visitor(ctx, std::move(f)); + SimpleTransformVisitor<F> visitor(ctx, std::forward<F>(f)); QualType result = visitor.Visit(splitType.Ty); if (result.isNull()) return result; @@ -1072,13 +1081,24 @@ QualType QualType::substObjCTypeArgs( // Replace an Objective-C type parameter reference with the corresponding // type argument. - if (const auto *typedefTy = dyn_cast<TypedefType>(splitType.Ty)) { - if (auto *typeParam = dyn_cast<ObjCTypeParamDecl>(typedefTy->getDecl())) { + if (const auto *OTPTy = dyn_cast<ObjCTypeParamType>(splitType.Ty)) { + if (auto *typeParam = dyn_cast<ObjCTypeParamDecl>(OTPTy->getDecl())) { // If we have type arguments, use them. if (!typeArgs.empty()) { - // FIXME: Introduce SubstObjCTypeParamType ? QualType argType = typeArgs[typeParam->getIndex()]; - return ctx.getQualifiedType(argType, splitType.Quals); + if (OTPTy->qual_empty()) + return ctx.getQualifiedType(argType, splitType.Quals); + + // Apply protocol lists if exists. + bool hasError; + SmallVector<ObjCProtocolDecl*, 8> protocolsVec; + protocolsVec.append(OTPTy->qual_begin(), + OTPTy->qual_end()); + ArrayRef<ObjCProtocolDecl *> protocolsToApply = protocolsVec; + QualType resultTy = ctx.applyObjCProtocolQualifiers(argType, + protocolsToApply, hasError, true/*allowOnPointerType*/); + + return ctx.getQualifiedType(resultTy, splitType.Quals); } switch (context) { @@ -2317,6 +2337,15 @@ bool QualType::isCXX11PODType(const ASTContext &Context) const { return false; } +bool Type::isAlignValT() const { + if (auto *ET = getAs<EnumType>()) { + auto *II = ET->getDecl()->getIdentifier(); + if (II && II->isStr("align_val_t") && ET->getDecl()->isInStdNamespace()) + return true; + } + return false; +} + bool Type::isPromotableIntegerType() const { if (const BuiltinType *BT = getAs<BuiltinType>()) switch (BT->getKind()) { @@ -2638,6 +2667,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { case CC_X86VectorCall: return "vectorcall"; case CC_X86_64Win64: return "ms_abi"; case CC_X86_64SysV: return "sysv_abi"; + case CC_X86RegCall : return "regcall"; case CC_AAPCS: return "aapcs"; case CC_AAPCS_VFP: return "aapcs-vfp"; case CC_IntelOclBicc: return "intel_ocl_bicc"; @@ -2688,8 +2718,9 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, QualType *exnSlot = argSlot + NumParams; unsigned I = 0; for (QualType ExceptionType : epi.ExceptionSpec.Exceptions) { - // Note that a dependent exception specification does *not* make - // a type dependent; it's not even part of the C++ type system. + // Note that, before C++17, a dependent exception specification does + // *not* make a type dependent; it's not even part of the C++ type + // system. if (ExceptionType->isInstantiationDependentType()) setInstantiationDependent(); @@ -2728,6 +2759,19 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, slot[0] = epi.ExceptionSpec.SourceDecl; } + // If this is a canonical type, and its exception specification is dependent, + // then it's a dependent type. This only happens in C++17 onwards. + if (isCanonicalUnqualified()) { + if (getExceptionSpecType() == EST_Dynamic || + getExceptionSpecType() == EST_ComputedNoexcept) { + assert(hasDependentExceptionSpec() && "type should not be canonical"); + setDependent(); + } + } else if (getCanonicalTypeInternal()->isDependentType()) { + // Ask our canonical type whether our exception specification was dependent. + setDependent(); + } + if (epi.ExtParameterInfos) { ExtParameterInfo *extParamInfos = const_cast<ExtParameterInfo *>(getExtParameterInfosBuffer()); @@ -2748,6 +2792,15 @@ bool FunctionProtoType::hasDependentExceptionSpec() const { return false; } +bool FunctionProtoType::hasInstantiationDependentExceptionSpec() const { + if (Expr *NE = getNoexceptExpr()) + return NE->isInstantiationDependent(); + for (QualType ET : exceptions()) + if (ET->isInstantiationDependentType()) + return true; + return false; +} + FunctionProtoType::NoexceptResult FunctionProtoType::getNoexceptSpec(const ASTContext &ctx) const { ExceptionSpecificationType est = getExceptionSpecType(); @@ -2772,29 +2825,28 @@ FunctionProtoType::getNoexceptSpec(const ASTContext &ctx) const { return value.getBoolValue() ? NR_Nothrow : NR_Throw; } -bool FunctionProtoType::isNothrow(const ASTContext &Ctx, - bool ResultIfDependent) const { +CanThrowResult FunctionProtoType::canThrow(const ASTContext &Ctx) const { ExceptionSpecificationType EST = getExceptionSpecType(); assert(EST != EST_Unevaluated && EST != EST_Uninstantiated); if (EST == EST_DynamicNone || EST == EST_BasicNoexcept) - return true; + return CT_Cannot; - if (EST == EST_Dynamic && ResultIfDependent) { + if (EST == EST_Dynamic) { // A dynamic exception specification is throwing unless every exception // type is an (unexpanded) pack expansion type. for (unsigned I = 0, N = NumExceptions; I != N; ++I) if (!getExceptionType(I)->getAs<PackExpansionType>()) - return false; - return ResultIfDependent; + return CT_Can; + return CT_Dependent; } if (EST != EST_ComputedNoexcept) - return false; + return CT_Can; NoexceptResult NR = getNoexceptSpec(Ctx); if (NR == NR_Dependent) - return ResultIfDependent; - return NR == NR_Nothrow; + return CT_Dependent; + return NR == NR_Nothrow ? CT_Cannot : CT_Can; } bool FunctionProtoType::isTemplateVariadic() const { @@ -2808,7 +2860,7 @@ bool FunctionProtoType::isTemplateVariadic() const { void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, const QualType *ArgTys, unsigned NumParams, const ExtProtoInfo &epi, - const ASTContext &Context) { + const ASTContext &Context, bool Canonical) { // We have to be careful not to get ambiguous profile encodings. // Note that valid type pointers are never ambiguous with anything else. @@ -2847,7 +2899,7 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, ID.AddPointer(Ex.getAsOpaquePtr()); } else if (epi.ExceptionSpec.Type == EST_ComputedNoexcept && epi.ExceptionSpec.NoexceptExpr) { - epi.ExceptionSpec.NoexceptExpr->Profile(ID, Context, false); + epi.ExceptionSpec.NoexceptExpr->Profile(ID, Context, Canonical); } else if (epi.ExceptionSpec.Type == EST_Uninstantiated || epi.ExceptionSpec.Type == EST_Unevaluated) { ID.AddPointer(epi.ExceptionSpec.SourceDecl->getCanonicalDecl()); @@ -2863,7 +2915,7 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) { Profile(ID, getReturnType(), param_type_begin(), NumParams, getExtProtoInfo(), - Ctx); + Ctx, isCanonicalUnqualified()); } QualType TypedefType::desugar() const { @@ -2992,6 +3044,7 @@ bool AttributedType::isQualifier() const { case AttributedType::attr_fastcall: case AttributedType::attr_stdcall: case AttributedType::attr_thiscall: + case AttributedType::attr_regcall: case AttributedType::attr_pascal: case AttributedType::attr_swiftcall: case AttributedType::attr_vectorcall: @@ -3049,6 +3102,7 @@ bool AttributedType::isCallingConv() const { case attr_fastcall: case attr_stdcall: case attr_thiscall: + case attr_regcall: case attr_swiftcall: case attr_vectorcall: case attr_pascal: @@ -3212,6 +3266,20 @@ void ObjCObjectTypeImpl::Profile(llvm::FoldingSetNodeID &ID) { isKindOfTypeAsWritten()); } +void ObjCTypeParamType::Profile(llvm::FoldingSetNodeID &ID, + const ObjCTypeParamDecl *OTPDecl, + ArrayRef<ObjCProtocolDecl *> protocols) { + ID.AddPointer(OTPDecl); + ID.AddInteger(protocols.size()); + for (auto proto : protocols) + ID.AddPointer(proto); +} + +void ObjCTypeParamType::Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getDecl(), + llvm::makeArrayRef(qual_begin(), getNumProtocols())); +} + namespace { /// \brief The cached properties of a type. @@ -3687,10 +3755,18 @@ bool Type::isObjCARCImplicitlyUnretainedType() const { } bool Type::isObjCNSObjectType() const { - if (const TypedefType *typedefType = dyn_cast<TypedefType>(this)) - return typedefType->getDecl()->hasAttr<ObjCNSObjectAttr>(); - return false; + const Type *cur = this; + while (true) { + if (const TypedefType *typedefType = dyn_cast<TypedefType>(cur)) + return typedefType->getDecl()->hasAttr<ObjCNSObjectAttr>(); + + // Single-step desugar until we run out of sugar. + QualType next = cur->getLocallyUnqualifiedSingleStepDesugaredType(); + if (next.getTypePtr() == cur) return false; + cur = next.getTypePtr(); + } } + bool Type::isObjCIndependentClassType() const { if (const TypedefType *typedefType = dyn_cast<TypedefType>(this)) return typedefType->getDecl()->hasAttr<ObjCIndependentClassAttr>(); diff --git a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp index 78947d1..7242858 100644 --- a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp @@ -16,10 +16,9 @@ #include "clang/AST/Expr.h" #include "clang/AST/TypeLocVisitor.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" using namespace clang; -static const unsigned TypeLocMaxDataAlign = llvm::alignOf<void *>(); +static const unsigned TypeLocMaxDataAlign = alignof(void *); //===----------------------------------------------------------------------===// // TypeLoc Implementation @@ -211,7 +210,7 @@ SourceLocation TypeLoc::getEndLoc() const { switch (Cur.getTypeLocClass()) { default: if (!Last) - Last = Cur; + Last = Cur; return Last.getLocalSourceRange().getEnd(); case Paren: case ConstantArray: @@ -389,6 +388,17 @@ TypeLoc TypeLoc::findExplicitQualifierLoc() const { return TypeLoc(); } +void ObjCTypeParamTypeLoc::initializeLocal(ASTContext &Context, + SourceLocation Loc) { + setNameLoc(Loc); + if (!getNumProtocols()) return; + + setProtocolLAngleLoc(Loc); + setProtocolRAngleLoc(Loc); + for (unsigned i = 0, e = getNumProtocols(); i != e; ++i) + setProtocolLoc(i, Loc); +} + void ObjCObjectTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) { setHasBaseTypeAsWritten(true); diff --git a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp index 065a2db..cccc908 100644 --- a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp @@ -194,6 +194,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::DependentName: case Type::DependentTemplateSpecialization: case Type::ObjCObject: + case Type::ObjCTypeParam: case Type::ObjCInterface: case Type::Atomic: case Type::Pipe: @@ -724,6 +725,9 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, case CC_X86_64SysV: OS << " __attribute__((sysv_abi))"; break; + case CC_X86RegCall: + OS << " __attribute__((regcall))"; + break; case CC_SpirFunction: case CC_OpenCLKernel: // Do nothing. These CCs are not available as attributes. @@ -897,6 +901,10 @@ void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) { } void TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); + if (T->isReadOnly()) + OS << "read_only "; + else + OS << "write_only "; OS << "pipe "; print(T->getElementType(), OS, StringRef()); spaceBeforePlaceHolder(OS); @@ -1338,6 +1346,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, case AttributedType::attr_pascal: OS << "pascal"; break; case AttributedType::attr_ms_abi: OS << "ms_abi"; break; case AttributedType::attr_sysv_abi: OS << "sysv_abi"; break; + case AttributedType::attr_regcall: OS << "regcall"; break; case AttributedType::attr_pcs: case AttributedType::attr_pcs_vfp: { OS << "pcs("; @@ -1368,6 +1377,28 @@ void TypePrinter::printObjCInterfaceBefore(const ObjCInterfaceType *T, void TypePrinter::printObjCInterfaceAfter(const ObjCInterfaceType *T, raw_ostream &OS) { } +void TypePrinter::printObjCTypeParamBefore(const ObjCTypeParamType *T, + raw_ostream &OS) { + OS << T->getDecl()->getName(); + if (!T->qual_empty()) { + bool isFirst = true; + OS << '<'; + for (const auto *I : T->quals()) { + if (isFirst) + isFirst = false; + else + OS << ','; + OS << I->getName(); + } + OS << '>'; + } + + spaceBeforePlaceHolder(OS); +} + +void TypePrinter::printObjCTypeParamAfter(const ObjCTypeParamType *T, + raw_ostream &OS) { } + void TypePrinter::printObjCObjectBefore(const ObjCObjectType *T, raw_ostream &OS) { if (T->qual_empty() && T->isUnspecializedAsWritten() && diff --git a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp index 640fbf4..e60ae33 100644 --- a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp @@ -777,9 +777,8 @@ public: typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> VBaseOffsetOffsetsMapTy; - - typedef llvm::DenseMap<BaseSubobject, uint64_t> - AddressPointsMapTy; + + typedef VTableLayout::AddressPointsMapTy AddressPointsMapTy; typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy; @@ -817,7 +816,7 @@ private: /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets for /// the most derived class. VBaseOffsetOffsetsMapTy VBaseOffsetOffsets; - + /// Components - The components of the vtable being built. SmallVector<VTableComponent, 64> Components; @@ -982,6 +981,10 @@ private: } public: + /// Component indices of the first component of each of the vtables in the + /// vtable group. + SmallVector<size_t, 4> VTableIndices; + ItaniumVTableBuilder(ItaniumVTableContext &VTables, const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset, @@ -1028,20 +1031,8 @@ public: return MethodVTableIndices.end(); } - /// getNumVTableComponents - Return the number of components in the vtable - /// currently built. - uint64_t getNumVTableComponents() const { - return Components.size(); - } + ArrayRef<VTableComponent> vtable_components() const { return Components; } - const VTableComponent *vtable_component_begin() const { - return Components.begin(); - } - - const VTableComponent *vtable_component_end() const { - return Components.end(); - } - AddressPointsMapTy::const_iterator address_points_begin() const { return AddressPoints.begin(); } @@ -1639,6 +1630,9 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables( bool BaseIsVirtualInLayoutClass, CharUnits OffsetInLayoutClass) { assert(Base.getBase()->isDynamicClass() && "class does not have a vtable!"); + unsigned VTableIndex = Components.size(); + VTableIndices.push_back(VTableIndex); + // Add vcall and vbase offsets for this vtable. VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, LayoutClass, &Overriders, Base, BaseIsVirtualInLayoutClass, @@ -1695,9 +1689,11 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables( // Add all address points. while (true) { - AddressPoints.insert(std::make_pair( - BaseSubobject(RD, OffsetInLayoutClass), - AddressPoint)); + AddressPoints.insert( + std::make_pair(BaseSubobject(RD, OffsetInLayoutClass), + VTableLayout::AddressPointLocation{ + unsigned(VTableIndices.size() - 1), + unsigned(AddressPoint - VTableIndex)})); const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); @@ -1901,7 +1897,8 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex; for (const auto &AP : AddressPoints) { const BaseSubobject &Base = AP.first; - uint64_t Index = AP.second; + uint64_t Index = + VTableIndices[AP.second.VTableIndex] + AP.second.AddressPointIndex; AddressPointsByIndex.insert(std::make_pair(Index, Base)); } @@ -2203,30 +2200,24 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { } } -VTableLayout::VTableLayout(uint64_t NumVTableComponents, - const VTableComponent *VTableComponents, - uint64_t NumVTableThunks, - const VTableThunkTy *VTableThunks, - const AddressPointsMapTy &AddressPoints, - bool IsMicrosoftABI) - : NumVTableComponents(NumVTableComponents), - VTableComponents(new VTableComponent[NumVTableComponents]), - NumVTableThunks(NumVTableThunks), - VTableThunks(new VTableThunkTy[NumVTableThunks]), - AddressPoints(AddressPoints), - IsMicrosoftABI(IsMicrosoftABI) { - std::copy(VTableComponents, VTableComponents+NumVTableComponents, - this->VTableComponents.get()); - std::copy(VTableThunks, VTableThunks+NumVTableThunks, - this->VTableThunks.get()); - std::sort(this->VTableThunks.get(), - this->VTableThunks.get() + NumVTableThunks, +VTableLayout::VTableLayout(ArrayRef<size_t> VTableIndices, + ArrayRef<VTableComponent> VTableComponents, + ArrayRef<VTableThunkTy> VTableThunks, + const AddressPointsMapTy &AddressPoints) + : VTableComponents(VTableComponents), VTableThunks(VTableThunks), + AddressPoints(AddressPoints) { + if (VTableIndices.size() <= 1) + assert(VTableIndices.size() == 1 && VTableIndices[0] == 0); + else + this->VTableIndices = OwningArrayRef<size_t>(VTableIndices); + + std::sort(this->VTableThunks.begin(), this->VTableThunks.end(), [](const VTableLayout::VTableThunkTy &LHS, const VTableLayout::VTableThunkTy &RHS) { - assert((LHS.first != RHS.first || LHS.second == RHS.second) && - "Different thunks should have unique indices!"); - return LHS.first < RHS.first; - }); + assert((LHS.first != RHS.first || LHS.second == RHS.second) && + "Different thunks should have unique indices!"); + return LHS.first < RHS.first; + }); } VTableLayout::~VTableLayout() { } @@ -2234,9 +2225,7 @@ VTableLayout::~VTableLayout() { } ItaniumVTableContext::ItaniumVTableContext(ASTContext &Context) : VTableContextBase(/*MS=*/false) {} -ItaniumVTableContext::~ItaniumVTableContext() { - llvm::DeleteContainerSeconds(VTableLayouts); -} +ItaniumVTableContext::~ItaniumVTableContext() {} uint64_t ItaniumVTableContext::getMethodVTableIndex(GlobalDecl GD) { MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD); @@ -2280,21 +2269,19 @@ ItaniumVTableContext::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, return I->second; } -static VTableLayout *CreateVTableLayout(const ItaniumVTableBuilder &Builder) { +static std::unique_ptr<VTableLayout> +CreateVTableLayout(const ItaniumVTableBuilder &Builder) { SmallVector<VTableLayout::VTableThunkTy, 1> VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end()); - return new VTableLayout(Builder.getNumVTableComponents(), - Builder.vtable_component_begin(), - VTableThunks.size(), - VTableThunks.data(), - Builder.getAddressPoints(), - /*IsMicrosoftABI=*/false); + return llvm::make_unique<VTableLayout>( + Builder.VTableIndices, Builder.vtable_components(), VTableThunks, + Builder.getAddressPoints()); } void ItaniumVTableContext::computeVTableRelatedInformation(const CXXRecordDecl *RD) { - const VTableLayout *&Entry = VTableLayouts[RD]; + std::unique_ptr<const VTableLayout> &Entry = VTableLayouts[RD]; // Check if we've computed this information before. if (Entry) @@ -2330,7 +2317,8 @@ ItaniumVTableContext::computeVTableRelatedInformation(const CXXRecordDecl *RD) { } } -VTableLayout *ItaniumVTableContext::createConstructionVTableLayout( +std::unique_ptr<VTableLayout> +ItaniumVTableContext::createConstructionVTableLayout( const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset, bool MostDerivedClassIsVirtual, const CXXRecordDecl *LayoutClass) { ItaniumVTableBuilder Builder(*this, MostDerivedClass, MostDerivedClassOffset, @@ -2538,12 +2526,12 @@ private: public: VFTableBuilder(MicrosoftVTableContext &VTables, - const CXXRecordDecl *MostDerivedClass, const VPtrInfo *Which) + const CXXRecordDecl *MostDerivedClass, const VPtrInfo &Which) : VTables(VTables), Context(MostDerivedClass->getASTContext()), MostDerivedClass(MostDerivedClass), MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)), - WhichVFPtr(*Which), + WhichVFPtr(Which), Overriders(MostDerivedClass, CharUnits(), MostDerivedClass) { // Provide the RTTI component if RTTIData is enabled. If the vftable would // be available externally, we should not provide the RTTI componenent. It @@ -2570,15 +2558,7 @@ public: MethodVFTableLocations.end()); } - uint64_t getNumVTableComponents() const { return Components.size(); } - - const VTableComponent *vtable_component_begin() const { - return Components.begin(); - } - - const VTableComponent *vtable_component_end() const { - return Components.end(); - } + ArrayRef<VTableComponent> vtable_components() const { return Components; } VTableThunksMapTy::const_iterator vtable_thunks_begin() const { return VTableThunks.begin(); @@ -2931,8 +2911,8 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, // class. const CXXRecordDecl *NextBase = nullptr, *NextLastVBase = LastVBase; CharUnits NextBaseOffset; - if (BaseDepth < WhichVFPtr.PathToBaseWithVPtr.size()) { - NextBase = WhichVFPtr.PathToBaseWithVPtr[BaseDepth]; + if (BaseDepth < WhichVFPtr.PathToIntroducingObject.size()) { + NextBase = WhichVFPtr.PathToIntroducingObject[BaseDepth]; if (isDirectVBase(NextBase, RD)) { NextLastVBase = NextBase; NextBaseOffset = MostDerivedClassLayout.getVBaseClassOffset(NextBase); @@ -3124,7 +3104,7 @@ static void dumpMicrosoftThunkAdjustment(const ThunkInfo &TI, raw_ostream &Out, void VFTableBuilder::dumpLayout(raw_ostream &Out) { Out << "VFTable for "; - PrintBasePath(WhichVFPtr.PathToBaseWithVPtr, Out); + PrintBasePath(WhichVFPtr.PathToIntroducingObject, Out); Out << "'"; MostDerivedClass->printQualifiedName(Out); Out << "' (" << Components.size() @@ -3278,7 +3258,7 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables, // Base case: this subobject has its own vptr. if (ForVBTables ? Layout.hasOwnVBPtr() : Layout.hasOwnVFPtr()) - Paths.push_back(new VPtrInfo(RD)); + Paths.push_back(llvm::make_unique<VPtrInfo>(RD)); // Recursive case: get all the vbtables from our bases and remove anything // that shares a virtual base. @@ -3294,14 +3274,14 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables, const VPtrInfoVector &BasePaths = ForVBTables ? enumerateVBTables(Base) : getVFPtrOffsets(Base); - for (VPtrInfo *BaseInfo : BasePaths) { + for (const std::unique_ptr<VPtrInfo> &BaseInfo : BasePaths) { // Don't include the path if it goes through a virtual base that we've // already included. if (setsIntersect(VBasesSeen, BaseInfo->ContainingVBases)) continue; // Copy the path and adjust it as necessary. - VPtrInfo *P = new VPtrInfo(*BaseInfo); + auto P = llvm::make_unique<VPtrInfo>(*BaseInfo); // We mangle Base into the path if the path would've been ambiguous and it // wasn't already extended with Base. @@ -3311,10 +3291,10 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables, // Keep track of which vtable the derived class is going to extend with // new methods or bases. We append to either the vftable of our primary // base, or the first non-virtual base that has a vbtable. - if (P->ReusingBase == Base && + if (P->ObjectWithVPtr == Base && Base == (ForVBTables ? Layout.getBaseSharingVBPtr() : Layout.getPrimaryBase())) - P->ReusingBase = RD; + P->ObjectWithVPtr = RD; // Keep track of the full adjustment from the MDC to this vtable. The // adjustment is captured by an optional vbase and a non-virtual offset. @@ -3328,7 +3308,7 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables, if (const CXXRecordDecl *VB = P->getVBaseWithVPtr()) P->FullOffsetInMDC += Layout.getVBaseClassOffset(VB); - Paths.push_back(P); + Paths.push_back(std::move(P)); } if (B.isVirtual()) @@ -3347,10 +3327,10 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables, Changed = rebucketPaths(Paths); } -static bool extendPath(VPtrInfo *P) { - if (P->NextBaseToMangle) { - P->MangledPath.push_back(P->NextBaseToMangle); - P->NextBaseToMangle = nullptr;// Prevent the path from being extended twice. +static bool extendPath(VPtrInfo &P) { + if (P.NextBaseToMangle) { + P.MangledPath.push_back(P.NextBaseToMangle); + P.NextBaseToMangle = nullptr;// Prevent the path from being extended twice. return true; } return false; @@ -3363,10 +3343,13 @@ static bool rebucketPaths(VPtrInfoVector &Paths) { // sorted vector to implement a multiset to form the buckets. Note that the // ordering is based on pointers, but it doesn't change our output order. The // current algorithm is designed to match MSVC 2012's names. - VPtrInfoVector PathsSorted(Paths); + llvm::SmallVector<std::reference_wrapper<VPtrInfo>, 2> PathsSorted; + PathsSorted.reserve(Paths.size()); + for (auto& P : Paths) + PathsSorted.push_back(*P); std::sort(PathsSorted.begin(), PathsSorted.end(), - [](const VPtrInfo *LHS, const VPtrInfo *RHS) { - return LHS->MangledPath < RHS->MangledPath; + [](const VPtrInfo &LHS, const VPtrInfo &RHS) { + return LHS.MangledPath < RHS.MangledPath; }); bool Changed = false; for (size_t I = 0, E = PathsSorted.size(); I != E;) { @@ -3374,8 +3357,9 @@ static bool rebucketPaths(VPtrInfoVector &Paths) { size_t BucketStart = I; do { ++I; - } while (I != E && PathsSorted[BucketStart]->MangledPath == - PathsSorted[I]->MangledPath); + } while (I != E && + PathsSorted[BucketStart].get().MangledPath == + PathsSorted[I].get().MangledPath); // If this bucket has multiple paths, extend them all. if (I - BucketStart > 1) { @@ -3387,13 +3371,7 @@ static bool rebucketPaths(VPtrInfoVector &Paths) { return Changed; } -MicrosoftVTableContext::~MicrosoftVTableContext() { - for (auto &P : VFPtrLocations) - llvm::DeleteContainerPointers(*P.second); - llvm::DeleteContainerSeconds(VFPtrLocations); - llvm::DeleteContainerSeconds(VFTableLayouts); - llvm::DeleteContainerSeconds(VBaseInfo); -} +MicrosoftVTableContext::~MicrosoftVTableContext() {} namespace { typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>, @@ -3401,14 +3379,14 @@ typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>, } // This recursive function finds all paths from a subobject centered at -// (RD, Offset) to the subobject located at BaseWithVPtr. +// (RD, Offset) to the subobject located at IntroducingObject. static void findPathsToSubobject(ASTContext &Context, const ASTRecordLayout &MostDerivedLayout, const CXXRecordDecl *RD, CharUnits Offset, - BaseSubobject BaseWithVPtr, + BaseSubobject IntroducingObject, FullPathTy &FullPath, std::list<FullPathTy> &Paths) { - if (BaseSubobject(RD, Offset) == BaseWithVPtr) { + if (BaseSubobject(RD, Offset) == IntroducingObject) { Paths.push_back(FullPath); return; } @@ -3422,7 +3400,7 @@ static void findPathsToSubobject(ASTContext &Context, : Offset + Layout.getBaseClassOffset(Base); FullPath.insert(BaseSubobject(Base, NewOffset)); findPathsToSubobject(Context, MostDerivedLayout, Base, NewOffset, - BaseWithVPtr, FullPath, Paths); + IntroducingObject, FullPath, Paths); FullPath.pop_back(); } } @@ -3477,7 +3455,8 @@ static CharUnits getOffsetOfFullPath(ASTContext &Context, // two paths introduce overrides which the other path doesn't contain, issue a // diagnostic. static const FullPathTy *selectBestPath(ASTContext &Context, - const CXXRecordDecl *RD, VPtrInfo *Info, + const CXXRecordDecl *RD, + const VPtrInfo &Info, std::list<FullPathTy> &FullPaths) { // Handle some easy cases first. if (FullPaths.empty()) @@ -3497,7 +3476,7 @@ static const FullPathTy *selectBestPath(ASTContext &Context, CharUnits BaseOffset = getOffsetOfFullPath(Context, TopLevelRD, SpecificPath); FinalOverriders Overriders(TopLevelRD, CharUnits::Zero(), TopLevelRD); - for (const CXXMethodDecl *MD : Info->BaseWithVPtr->methods()) { + for (const CXXMethodDecl *MD : Info.IntroducingObject->methods()) { if (!MD->isVirtual()) continue; FinalOverriders::OverriderInfo OI = @@ -3552,18 +3531,18 @@ static void computeFullPathsForVFTables(ASTContext &Context, const ASTRecordLayout &MostDerivedLayout = Context.getASTRecordLayout(RD); FullPathTy FullPath; std::list<FullPathTy> FullPaths; - for (VPtrInfo *Info : Paths) { + for (const std::unique_ptr<VPtrInfo>& Info : Paths) { findPathsToSubobject( Context, MostDerivedLayout, RD, CharUnits::Zero(), - BaseSubobject(Info->BaseWithVPtr, Info->FullOffsetInMDC), FullPath, + BaseSubobject(Info->IntroducingObject, Info->FullOffsetInMDC), FullPath, FullPaths); FullPath.clear(); removeRedundantPaths(FullPaths); - Info->PathToBaseWithVPtr.clear(); + Info->PathToIntroducingObject.clear(); if (const FullPathTy *BestPath = - selectBestPath(Context, RD, Info, FullPaths)) + selectBestPath(Context, RD, *Info, FullPaths)) for (const BaseSubobject &BSO : *BestPath) - Info->PathToBaseWithVPtr.push_back(BSO.getBase()); + Info->PathToIntroducingObject.push_back(BSO.getBase()); FullPaths.clear(); } } @@ -3578,22 +3557,24 @@ void MicrosoftVTableContext::computeVTableRelatedInformation( const VTableLayout::AddressPointsMapTy EmptyAddressPointsMap; - VPtrInfoVector *VFPtrs = new VPtrInfoVector(); - computeVTablePaths(/*ForVBTables=*/false, RD, *VFPtrs); - computeFullPathsForVFTables(Context, RD, *VFPtrs); - VFPtrLocations[RD] = VFPtrs; + { + VPtrInfoVector VFPtrs; + computeVTablePaths(/*ForVBTables=*/false, RD, VFPtrs); + computeFullPathsForVFTables(Context, RD, VFPtrs); + VFPtrLocations[RD] = std::move(VFPtrs); + } MethodVFTableLocationsTy NewMethodLocations; - for (const VPtrInfo *VFPtr : *VFPtrs) { - VFTableBuilder Builder(*this, RD, VFPtr); + for (const std::unique_ptr<VPtrInfo> &VFPtr : VFPtrLocations[RD]) { + VFTableBuilder Builder(*this, RD, *VFPtr); VFTableIdTy id(RD, VFPtr->FullOffsetInMDC); assert(VFTableLayouts.count(id) == 0); SmallVector<VTableLayout::VTableThunkTy, 1> VTableThunks( Builder.vtable_thunks_begin(), Builder.vtable_thunks_end()); - VFTableLayouts[id] = new VTableLayout( - Builder.getNumVTableComponents(), Builder.vtable_component_begin(), - VTableThunks.size(), VTableThunks.data(), EmptyAddressPointsMap, true); + VFTableLayouts[id] = llvm::make_unique<VTableLayout>( + ArrayRef<size_t>{0}, Builder.vtable_components(), VTableThunks, + EmptyAddressPointsMap); Thunks.insert(Builder.thunks_begin(), Builder.thunks_end()); for (const auto &Loc : Builder.vtable_locations()) { @@ -3670,17 +3651,18 @@ void MicrosoftVTableContext::dumpMethodLocations( Out.flush(); } -const VirtualBaseInfo *MicrosoftVTableContext::computeVBTableRelatedInformation( +const VirtualBaseInfo &MicrosoftVTableContext::computeVBTableRelatedInformation( const CXXRecordDecl *RD) { VirtualBaseInfo *VBI; { // Get or create a VBI for RD. Don't hold a reference to the DenseMap cell, // as it may be modified and rehashed under us. - VirtualBaseInfo *&Entry = VBaseInfo[RD]; + std::unique_ptr<VirtualBaseInfo> &Entry = VBaseInfo[RD]; if (Entry) - return Entry; - Entry = VBI = new VirtualBaseInfo(); + return *Entry; + Entry = llvm::make_unique<VirtualBaseInfo>(); + VBI = Entry.get(); } computeVTablePaths(/*ForVBTables=*/true, RD, VBI->VBPtrPaths); @@ -3690,10 +3672,10 @@ const VirtualBaseInfo *MicrosoftVTableContext::computeVBTableRelatedInformation( if (const CXXRecordDecl *VBPtrBase = Layout.getBaseSharingVBPtr()) { // If the Derived class shares the vbptr with a non-virtual base, the shared // virtual bases come first so that the layout is the same. - const VirtualBaseInfo *BaseInfo = + const VirtualBaseInfo &BaseInfo = computeVBTableRelatedInformation(VBPtrBase); - VBI->VBTableIndices.insert(BaseInfo->VBTableIndices.begin(), - BaseInfo->VBTableIndices.end()); + VBI->VBTableIndices.insert(BaseInfo.VBTableIndices.begin(), + BaseInfo.VBTableIndices.end()); } // New vbases are added to the end of the vbtable. @@ -3705,19 +3687,19 @@ const VirtualBaseInfo *MicrosoftVTableContext::computeVBTableRelatedInformation( VBI->VBTableIndices[CurVBase] = VBTableIndex++; } - return VBI; + return *VBI; } unsigned MicrosoftVTableContext::getVBTableIndex(const CXXRecordDecl *Derived, const CXXRecordDecl *VBase) { - const VirtualBaseInfo *VBInfo = computeVBTableRelatedInformation(Derived); - assert(VBInfo->VBTableIndices.count(VBase)); - return VBInfo->VBTableIndices.find(VBase)->second; + const VirtualBaseInfo &VBInfo = computeVBTableRelatedInformation(Derived); + assert(VBInfo.VBTableIndices.count(VBase)); + return VBInfo.VBTableIndices.find(VBase)->second; } const VPtrInfoVector & MicrosoftVTableContext::enumerateVBTables(const CXXRecordDecl *RD) { - return computeVBTableRelatedInformation(RD)->VBPtrPaths; + return computeVBTableRelatedInformation(RD).VBPtrPaths; } const VPtrInfoVector & @@ -3725,7 +3707,7 @@ MicrosoftVTableContext::getVFPtrOffsets(const CXXRecordDecl *RD) { computeVTableRelatedInformation(RD); assert(VFPtrLocations.count(RD) && "Couldn't find vfptr locations"); - return *VFPtrLocations[RD]; + return VFPtrLocations[RD]; } const VTableLayout & |