diff options
author | dim <dim@FreeBSD.org> | 2017-09-26 19:56:36 +0000 |
---|---|---|
committer | Luiz Souza <luiz@netgate.com> | 2018-02-21 15:12:19 -0300 |
commit | 1dcd2e8d24b295bc73e513acec2ed1514bb66be4 (patch) | |
tree | 4bd13a34c251e980e1a6b13584ca1f63b0dfe670 /contrib/llvm/tools/clang/lib/AST | |
parent | f45541ca2a56a1ba1202f94c080b04e96c1fa239 (diff) | |
download | FreeBSD-src-1dcd2e8d24b295bc73e513acec2ed1514bb66be4.zip FreeBSD-src-1dcd2e8d24b295bc73e513acec2ed1514bb66be4.tar.gz |
Merge clang, llvm, lld, lldb, compiler-rt and libc++ 5.0.0 release.
MFC r309126 (by emaste):
Correct lld llvm-tblgen dependency file name
MFC r309169:
Get rid of separate Subversion mergeinfo properties for llvm-dwarfdump
and llvm-lto. The mergeinfo confuses Subversion enormously, and these
directories will just use the mergeinfo for llvm itself.
MFC r312765:
Pull in r276136 from upstream llvm trunk (by Wei Mi):
Use ValueOffsetPair to enhance value reuse during SCEV expansion.
In D12090, the ExprValueMap was added to reuse existing value during
SCEV expansion. However, const folding and sext/zext distribution can
make the reuse still difficult.
A simplified case is: suppose we know S1 expands to V1 in
ExprValueMap, and
S1 = S2 + C_a
S3 = S2 + C_b
where C_a and C_b are different SCEVConstants. Then we'd like to
expand S3 as V1 - C_a + C_b instead of expanding S2 literally. It is
helpful when S2 is a complex SCEV expr and S2 has no entry in
ExprValueMap, which is usually caused by the fact that S3 is
generated from S1 after const folding.
In order to do that, we represent ExprValueMap as a mapping from SCEV
to ValueOffsetPair. We will save both S1->{V1, 0} and S2->{V1, C_a}
into the ExprValueMap when we create SCEV for V1. When S3 is
expanded, it will first expand S2 to V1 - C_a because of S2->{V1,
C_a} in the map, then expand S3 to V1 - C_a + C_b.
Differential Revision: https://reviews.llvm.org/D21313
This should fix assertion failures when building OpenCV >= 3.1.
PR: 215649
MFC r312831:
Revert r312765 for now, since it causes assertions when building
lang/spidermonkey24.
Reported by: antoine
PR: 215649
MFC r316511 (by jhb):
Add an implementation of __ffssi2() derived from __ffsdi2().
Newer versions of GCC include an __ffssi2() symbol in libgcc and the
compiler can emit calls to it in generated code. This is true for at
least GCC 6.2 when compiling world for mips and mips64.
Reviewed by: jmallett, dim
Sponsored by: DARPA / AFRL
Differential Revision: https://reviews.freebsd.org/D10086
MFC r318601 (by adrian):
[libcompiler-rt] add bswapdi2/bswapsi2
This is required for mips gcc 6.3 userland to build/run.
Reviewed by: emaste, dim
Approved by: emaste
Differential Revision: https://reviews.freebsd.org/D10838
MFC r318884 (by emaste):
lldb: map TRAP_CAP to a trace trap
In the absense of a more specific handler for TRAP_CAP (generated by
ENOTCAPABLE or ECAPMODE while in capability mode) treat it as a trace
trap.
Example usage (testing the bug in PR219173):
% proccontrol -m trapcap lldb usr.bin/hexdump/obj/hexdump -- -Cv -s 1 /bin/ls
...
(lldb) run
Process 12980 launching
Process 12980 launched: '.../usr.bin/hexdump/obj/hexdump' (x86_64)
Process 12980 stopped
* thread #1, stop reason = trace
frame #0: 0x0000004b80c65f1a libc.so.7`__sys_lseek + 10
...
In the future we should have LLDB control the trapcap procctl itself
(as it does with ASLR), as well as report a specific stop reason.
This change eliminates an assertion failure from LLDB for now.
MFC r319796:
Remove a few unneeded files from libllvm, libclang and liblldb.
MFC r319885 (by emaste):
lld: ELF: Fix ICF crash on absolute symbol relocations.
If two sections contained relocations to absolute symbols with the same
value we would crash when trying to access their sections. Add a check that
both symbols point to sections before accessing their sections, and treat
absolute symbols as equal if their values are equal.
Obtained from: LLD commit r292578
MFC r319918:
Revert r319796 for now, it can cause undefined references when linking
in some circumstances.
Reported by: Shawn Webb <shawn.webb@hardenedbsd.org>
MFC r319957 (by emaste):
lld: Add armelf emulation mode
Obtained from: LLD r305375
MFC r321369:
Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to
5.0.0 (trunk r308421). Upstream has branched for the 5.0.0 release,
which should be in about a month. Please report bugs and regressions,
so we can get them into the release.
Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11
support to build; see UPDATING for more information.
MFC r321420:
Add a few more object files to liblldb, which should solve errors when
linking the lldb executable in some cases. In particular, when the
-ffunction-sections -fdata-sections options are turned off, or
ineffective.
Reported by: Shawn Webb, Mark Millard
MFC r321433:
Cleanup stale Options.inc files from the previous libllvm build for
clang 4.0.0. Otherwise, these can get included before the two newly
generated ones (which are different) for clang 5.0.0.
Reported by: Mark Millard
MFC r321439 (by bdrewery):
Move llvm Options.inc hack from r321433 for NO_CLEAN to lib/clang/libllvm.
The files are only ever generated to .OBJDIR, not to WORLDTMP (as a
sysroot) and are only ever included from a compilation. So using
a beforebuild target here removes the file before the compilation
tries to include it.
MFC r321664:
Pull in r308891 from upstream llvm trunk (by Benjamin Kramer):
[CodeGenPrepare] Cut off FindAllMemoryUses if there are too many uses.
This avoids excessive compile time. The case I'm looking at is
Function.cpp from an old version of LLVM that still had the giant
memcmp string matcher in it. Before r308322 this compiled in about 2
minutes, after it, clang takes infinite* time to compile it. With
this patch we're at 5 min, which is still bad but this is a
pathological case.
The cut off at 20 uses was chosen by looking at other cut-offs in LLVM
for user scanning. It's probably too high, but does the job and is
very unlikely to regress anything.
Fixes PR33900.
* I'm impatient and aborted after 15 minutes, on the bug report it was
killed after 2h.
Pull in r308986 from upstream llvm trunk (by Simon Pilgrim):
[X86][CGP] Reduce memcmp() expansion to 2 load pairs (PR33914)
D35067/rL308322 attempted to support up to 4 load pairs for memcmp
inlining which resulted in regressions for some optimized libc memcmp
implementations (PR33914).
Until we can match these more optimal cases, this patch reduces the
memcmp expansion to a maximum of 2 load pairs (which matches what we
do for -Os).
This patch should be considered for the 5.0.0 release branch as well
Differential Revision: https://reviews.llvm.org/D35830
These fix a hang (or extremely long compile time) when building older
LLVM ports.
Reported by: antoine
PR: 219139
MFC r321719:
Pull in r309503 from upstream clang trunk (by Richard Smith):
PR33902: Invalidate line number cache when adding more text to
existing buffer.
This led to crashes as the line number cache would report a bogus
line number for a line of code, and we'd try to find a nonexistent
column within the line when printing diagnostics.
This fixes an assertion when building the graphics/champlain port.
Reported by: antoine, kwm
PR: 219139
MFC r321723:
Upgrade our copies of clang, llvm, lld and lldb to r309439 from the
upstream release_50 branch. This is just after upstream's 5.0.0-rc1.
MFC r322320:
Upgrade our copies of clang, llvm and libc++ to r310316 from the
upstream release_50 branch.
MFC r322326 (by emaste):
lldb: Make i386-*-freebsd expression work on JIT path
* Enable i386 ABI creation for freebsd
* Added an extra argument in ABISysV_i386::PrepareTrivialCall for mmap
syscall
* Unlike linux, the last argument of mmap is actually 64-bit(off_t).
This requires us to push an additional word for the higher order bits.
* Prior to this change, ktrace dump will show mmap failures due to
invalid argument coming from the 6th mmap argument.
Submitted by: Karnajit Wangkhem
Differential Revision: https://reviews.llvm.org/D34776
MFC r322360 (by emaste):
lldb: Report inferior signals as signals, not exceptions, on FreeBSD
This is the FreeBSD equivalent of LLVM r238549.
This serves 2 purposes:
* LLDB should handle inferior process signals SIGSEGV/SIGILL/SIGBUS/
SIGFPE the way it is suppose to be handled. Prior to this fix these
signals will neither create a coredump, nor exit from the debugger
or work for signal handling scenario.
* eInvalidCrashReason need not report "unknown crash reason" if we have
a valid si_signo
llvm.org/pr23699
Patch by Karnajit Wangkhem
Differential Revision: https://reviews.llvm.org/D35223
Submitted by: Karnajit Wangkhem
Obtained from: LLVM r310591
MFC r322474 (by emaste):
lld: Add `-z muldefs` option.
Obtained from: LLVM r310757
MFC r322740:
Upgrade our copies of clang, llvm, lld and libc++ to r311219 from the
upstream release_50 branch.
MFC r322855:
Upgrade our copies of clang, llvm, lldb and compiler-rt to r311606 from
the upstream release_50 branch.
As of this version, lib/msun's trig test should also work correctly
again (see bug 220989 for more information).
PR: 220989
MFC r323112:
Upgrade our copies of clang, llvm, lldb and compiler-rt to r312293 from
the upstream release_50 branch. This corresponds to 5.0.0 rc4.
As of this version, the cad/stepcode port should now compile in a more
reasonable time on i386 (see bug 221836 for more information).
PR: 221836
MFC r323245:
Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to
5.0.0 release (upstream r312559).
Release notes for llvm, clang and lld will be available here soon:
<http://releases.llvm.org/5.0.0/docs/ReleaseNotes.html>
<http://releases.llvm.org/5.0.0/tools/clang/docs/ReleaseNotes.html>
<http://releases.llvm.org/5.0.0/tools/lld/docs/ReleaseNotes.html>
Relnotes: yes
(cherry picked from commit 12cd91cf4c6b96a24427c0de5374916f2808d263)
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST')
38 files changed, 4538 insertions, 2060 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp index b531a66..c60373c 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp @@ -703,6 +703,7 @@ static const LangAS::Map *getAddressSpaceMap(const TargetInfo &T, // The fake address space map must have a distinct entry for each // language-specific address space. static const unsigned FakeAddrSpaceMap[] = { + 0, // Default 1, // opencl_global 3, // opencl_local 2, // opencl_constant @@ -748,6 +749,8 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, ExternCContext(nullptr), MakeIntegerSeqDecl(nullptr), TypePackElementDecl(nullptr), SourceMgr(SM), LangOpts(LOpts), SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)), + XRayFilter(new XRayFunctionFilter(LangOpts.XRayAlwaysInstrumentFiles, + LangOpts.XRayNeverInstrumentFiles, SM)), AddrSpaceMap(nullptr), Target(nullptr), AuxTarget(nullptr), PrintingPolicy(LOpts), Idents(idents), Selectors(sels), BuiltinInfo(builtins), DeclarationNames(*this), ExternalSource(nullptr), @@ -891,7 +894,7 @@ void ASTContext::mergeDefinitionIntoModule(NamedDecl *ND, Module *M, if (getLangOpts().ModulesLocalVisibility) MergedDefModules[ND].push_back(M); else - ND->setHidden(false); + ND->setVisibleDespiteOwningModule(); } void ASTContext::deduplicateMergedDefinitonsFor(NamedDecl *ND) { @@ -1167,7 +1170,6 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target, InitBuiltinType(OCLEventTy, BuiltinType::OCLEvent); InitBuiltinType(OCLClkEventTy, BuiltinType::OCLClkEvent); InitBuiltinType(OCLQueueTy, BuiltinType::OCLQueue); - InitBuiltinType(OCLNDRangeTy, BuiltinType::OCLNDRange); InitBuiltinType(OCLReserveIDTy, BuiltinType::OCLReserveID); } @@ -1474,6 +1476,8 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const { } } Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr())); + if (BaseT.getQualifiers().hasUnaligned()) + Align = Target->getCharWidth(); if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (VD->hasGlobalStorage() && !ForAlignof) Align = std::max(Align, getTargetInfo().getMinGlobalAlign()); @@ -1775,7 +1779,6 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: case BuiltinType::OCLQueue: - case BuiltinType::OCLNDRange: case BuiltinType::OCLReserveID: // Currently these types are pointers to opaque types. Width = Target->getPointerWidth(0); @@ -1877,8 +1880,9 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { return getTypeInfo(cast<SubstTemplateTypeParmType>(T)-> getReplacementType().getTypePtr()); - case Type::Auto: { - const AutoType *A = cast<AutoType>(T); + case Type::Auto: + case Type::DeducedTemplateSpecialization: { + const DeducedType *A = cast<DeducedType>(T); assert(!A->getDeducedType().isNull() && "cannot request the size of an undeduced or dependent auto type"); return getTypeInfo(A->getDeducedType().getTypePtr()); @@ -1935,9 +1939,8 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { break; case Type::Pipe: { - TypeInfo Info = getTypeInfo(cast<PipeType>(T)->getElementType()); - Width = Info.Width; - Align = Info.Align; + Width = Target->getPointerWidth(getTargetAddressSpace(LangAS::opencl_global)); + Align = Target->getPointerAlign(getTargetAddressSpace(LangAS::opencl_global)); } } @@ -2691,8 +2694,7 @@ QualType ASTContext::getConstantArrayType(QualType EltTy, // Convert the array size into a canonical width matching the pointer size for // the target. llvm::APInt ArySize(ArySizeIn); - ArySize = - ArySize.zextOrTrunc(Target->getPointerWidth(getTargetAddressSpace(EltTy))); + ArySize = ArySize.zextOrTrunc(Target->getMaxPointerWidth()); llvm::FoldingSetNodeID ID; ConstantArrayType::Profile(ID, EltTy, ArySize, ASM, IndexTypeQuals); @@ -2765,6 +2767,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { case Type::TemplateTypeParm: case Type::SubstTemplateTypeParmPack: case Type::Auto: + case Type::DeducedTemplateSpecialization: case Type::PackExpansion: llvm_unreachable("type should never be variably-modified"); @@ -3562,7 +3565,7 @@ QualType ASTContext::getSubstTemplateTypeParmPackType( = new (*this, TypeAlignment) SubstTemplateTypeParmPackType(Parm, Canon, ArgPack); Types.push_back(SubstParm); - SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos); + SubstTemplateTypeParmPackTypes.InsertNode(SubstParm, InsertPos); return QualType(SubstParm, 0); } @@ -3785,12 +3788,8 @@ QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, QualType Canon) const { if (Canon.isNull()) { NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); - ElaboratedTypeKeyword CanonKeyword = Keyword; - if (Keyword == ETK_None) - CanonKeyword = ETK_Typename; - - if (CanonNNS != NNS || CanonKeyword != Keyword) - Canon = getDependentNameType(CanonKeyword, CanonNNS, Name); + if (CanonNNS != NNS) + Canon = getDependentNameType(Keyword, CanonNNS, Name); } llvm::FoldingSetNodeID ID; @@ -3874,42 +3873,45 @@ ASTContext::getDependentTemplateSpecializationType( return QualType(T, 0); } +TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) { + 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); + + return Arg; +} + 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); - } + for (NamedDecl *Param : *Params) + Args.push_back(getInjectedTemplateArg(Param)); } QualType ASTContext::getPackExpansionType(QualType Pattern, @@ -4439,6 +4441,28 @@ QualType ASTContext::getAutoType(QualType DeducedType, AutoTypeKeyword Keyword, return QualType(AT, 0); } +/// Return the uniqued reference to the deduced template specialization type +/// which has been deduced to the given type, or to the canonical undeduced +/// such type, or the canonical deduced-but-dependent such type. +QualType ASTContext::getDeducedTemplateSpecializationType( + TemplateName Template, QualType DeducedType, bool IsDependent) const { + // Look in the folding set for an existing type. + void *InsertPos = nullptr; + llvm::FoldingSetNodeID ID; + DeducedTemplateSpecializationType::Profile(ID, Template, DeducedType, + IsDependent); + if (DeducedTemplateSpecializationType *DTST = + DeducedTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos)) + return QualType(DTST, 0); + + DeducedTemplateSpecializationType *DTST = new (*this, TypeAlignment) + DeducedTemplateSpecializationType(Template, DeducedType, IsDependent); + Types.push_back(DTST); + if (InsertPos) + DeducedTemplateSpecializationTypes.InsertNode(DTST, InsertPos); + return QualType(DTST, 0); +} + /// getAtomicType - Return the uniqued reference to the atomic type for /// the given value type. QualType ASTContext::getAtomicType(QualType T) const { @@ -4501,6 +4525,12 @@ CanQualType ASTContext::getSizeType() const { return getFromTargetType(Target->getSizeType()); } +/// Return the unique signed counterpart of the integer type +/// corresponding to size_t. +CanQualType ASTContext::getSignedSizeType() const { + return getFromTargetType(Target->getSignedSizeType()); +} + /// getIntMaxType - Return the unique type for "intmax_t" (C99 7.18.1.5). CanQualType ASTContext::getIntMaxType() const { return getFromTargetType(Target->getIntMaxType()); @@ -5922,7 +5952,6 @@ static char getObjCEncodingForPrimitiveKind(const ASTContext *C, case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: case BuiltinType::OCLQueue: - case BuiltinType::OCLNDRange: case BuiltinType::OCLReserveID: case BuiltinType::OCLSampler: case BuiltinType::Dependent: @@ -5967,9 +5996,19 @@ static void EncodeBitField(const ASTContext *Ctx, std::string& S, // compatibility with GCC, although providing it breaks anything that // actually uses runtime introspection and wants to work on both runtimes... if (Ctx->getLangOpts().ObjCRuntime.isGNUFamily()) { - const RecordDecl *RD = FD->getParent(); - const ASTRecordLayout &RL = Ctx->getASTRecordLayout(RD); - S += llvm::utostr(RL.getFieldOffset(FD->getFieldIndex())); + uint64_t Offset; + + if (const auto *IVD = dyn_cast<ObjCIvarDecl>(FD)) { + Offset = Ctx->lookupFieldBitOffset(IVD->getContainingInterface(), nullptr, + IVD); + } else { + const RecordDecl *RD = FD->getParent(); + const ASTRecordLayout &RL = Ctx->getASTRecordLayout(RD); + Offset = RL.getFieldOffset(FD->getFieldIndex()); + } + + S += llvm::utostr(Offset); + if (const EnumType *ET = T->getAs<EnumType>()) S += ObjCEncodingForEnumType(Ctx, ET); else { @@ -6216,6 +6255,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, S += "{objc_class=}"; return; } + // TODO: Double check to make sure this intentially falls through. + LLVM_FALLTHROUGH; } case Type::ObjCInterface: { @@ -6337,6 +6378,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, // We could see an undeduced auto type here during error recovery. // Just ignore it. case Type::Auto: + case Type::DeducedTemplateSpecialization: return; case Type::Pipe: @@ -7893,6 +7935,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, if (lbaseInfo.getProducesResult() != rbaseInfo.getProducesResult()) return QualType(); + if (lbaseInfo.getNoCallerSavedRegs() != rbaseInfo.getNoCallerSavedRegs()) + return QualType(); // FIXME: some uses, e.g. conditional exprs, really want this to be 'both'. bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn(); @@ -8043,20 +8087,12 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, Qualifiers LQuals = LHSCan.getLocalQualifiers(); Qualifiers RQuals = RHSCan.getLocalQualifiers(); if (LQuals != RQuals) { - if (getLangOpts().OpenCL) { - if (LHSCan.getUnqualifiedType() != RHSCan.getUnqualifiedType() || - LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers()) - return QualType(); - if (LQuals.isAddressSpaceSupersetOf(RQuals)) - return LHS; - if (RQuals.isAddressSpaceSupersetOf(LQuals)) - return RHS; - } // If any of these qualifiers are different, we have a type // mismatch. if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() || LQuals.getAddressSpace() != RQuals.getAddressSpace() || - LQuals.getObjCLifetime() != RQuals.getObjCLifetime()) + LQuals.getObjCLifetime() != RQuals.getObjCLifetime() || + LQuals.hasUnaligned() != RQuals.hasUnaligned()) return QualType(); // Exactly one GC qualifier difference is allowed: __strong is @@ -8136,6 +8172,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, llvm_unreachable("Non-canonical and dependent types shouldn't get here"); case Type::Auto: + case Type::DeducedTemplateSpecialization: case Type::LValueReference: case Type::RValueReference: case Type::MemberPointer: @@ -8175,6 +8212,20 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, LHSPointee = LHSPointee.getUnqualifiedType(); RHSPointee = RHSPointee.getUnqualifiedType(); } + if (getLangOpts().OpenCL) { + Qualifiers LHSPteeQual = LHSPointee.getQualifiers(); + Qualifiers RHSPteeQual = RHSPointee.getQualifiers(); + // Blocks can't be an expression in a ternary operator (OpenCL v2.0 + // 6.12.5) thus the following check is asymmetric. + if (!LHSPteeQual.isAddressSpaceSupersetOf(RHSPteeQual)) + return QualType(); + LHSPteeQual.removeAddressSpace(); + RHSPteeQual.removeAddressSpace(); + LHSPointee = + QualType(LHSPointee.getTypePtr(), LHSPteeQual.getAsOpaqueValue()); + RHSPointee = + QualType(RHSPointee.getTypePtr(), RHSPteeQual.getAsOpaqueValue()); + } QualType ResultType = mergeTypes(LHSPointee, RHSPointee, OfBlockPointer, Unqualified); if (ResultType.isNull()) return QualType(); @@ -8479,6 +8530,9 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, // Read the prefixed modifiers first. bool Done = false; + #ifndef NDEBUG + bool IsSpecialLong = false; + #endif while (!Done) { switch (*Str++) { default: Done = true; --Str; break; @@ -8496,12 +8550,28 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, Unsigned = true; break; case 'L': + assert(!IsSpecialLong && "Can't use 'L' with 'W' or 'N' modifiers"); assert(HowLong <= 2 && "Can't have LLLL modifier"); ++HowLong; break; + case 'N': { + // 'N' behaves like 'L' for all non LP64 targets and 'int' otherwise. + assert(!IsSpecialLong && "Can't use two 'N' or 'W' modifiers!"); + assert(HowLong == 0 && "Can't use both 'L' and 'N' modifiers!"); + #ifndef NDEBUG + IsSpecialLong = true; + #endif + if (Context.getTargetInfo().getLongWidth() == 32) + ++HowLong; + break; + } case 'W': // This modifier represents int64 type. + assert(!IsSpecialLong && "Can't use two 'N' or 'W' modifiers!"); assert(HowLong == 0 && "Can't use both 'L' and 'W' modifiers!"); + #ifndef NDEBUG + IsSpecialLong = true; + #endif switch (Context.getTargetInfo().getInt64Type()) { default: llvm_unreachable("Unexpected integer type"); @@ -8512,6 +8582,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, HowLong = 2; break; } + break; } } @@ -8696,7 +8767,8 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, char *End; unsigned AddrSpace = strtoul(Str, &End, 10); if (End != Str && AddrSpace != 0) { - Type = Context.getAddrSpaceQualType(Type, AddrSpace); + Type = Context.getAddrSpaceQualType( + Type, AddrSpace + LangAS::FirstTargetAddressSpace); Str = End; } if (c == '*') @@ -8788,7 +8860,7 @@ static GVALinkage basicGVALinkageForFunction(const ASTContext &Context, if (!FD->isExternallyVisible()) return GVA_Internal; - GVALinkage External = GVA_StrongExternal; + GVALinkage External; switch (FD->getTemplateSpecializationKind()) { case TSK_Undeclared: case TSK_ExplicitSpecialization: @@ -8860,8 +8932,22 @@ static GVALinkage adjustGVALinkageForAttributes(const ASTContext &Context, } GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const { - return adjustGVALinkageForAttributes( + auto L = adjustGVALinkageForAttributes( *this, basicGVALinkageForFunction(*this, FD), FD); + auto EK = ExternalASTSource::EK_ReplyHazy; + if (auto *Ext = getExternalSource()) + EK = Ext->hasExternalDefinitions(FD); + switch (EK) { + case ExternalASTSource::EK_Never: + if (L == GVA_DiscardableODR) + return GVA_StrongODR; + break; + case ExternalASTSource::EK_Always: + return GVA_AvailableExternally; + case ExternalASTSource::EK_ReplyHazy: + break; + } + return L; } static GVALinkage basicGVALinkageForVariable(const ASTContext &Context, @@ -8870,22 +8956,30 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context, return GVA_Internal; if (VD->isStaticLocal()) { - GVALinkage StaticLocalLinkage = GVA_DiscardableODR; const DeclContext *LexicalContext = VD->getParentFunctionOrMethod(); while (LexicalContext && !isa<FunctionDecl>(LexicalContext)) LexicalContext = LexicalContext->getLexicalParent(); - // Let the static local variable inherit its linkage from the nearest - // enclosing function. - if (LexicalContext) - StaticLocalLinkage = - Context.GetGVALinkageForFunction(cast<FunctionDecl>(LexicalContext)); + // ObjC Blocks can create local variables that don't have a FunctionDecl + // LexicalContext. + if (!LexicalContext) + return GVA_DiscardableODR; + + // Otherwise, let the static local variable inherit its linkage from the + // nearest enclosing function. + auto StaticLocalLinkage = + Context.GetGVALinkageForFunction(cast<FunctionDecl>(LexicalContext)); - // GVA_StrongODR function linkage is stronger than what we need, - // downgrade to GVA_DiscardableODR. - // This allows us to discard the variable if we never end up needing it. - return StaticLocalLinkage == GVA_StrongODR ? GVA_DiscardableODR - : StaticLocalLinkage; + // Itanium ABI 5.2.2: "Each COMDAT group [for a static local variable] must + // be emitted in any object with references to the symbol for the object it + // contains, whether inline or out-of-line." + // Similar behavior is observed with MSVC. An alternative ABI could use + // StrongODR/AvailableExternally to match the function, but none are + // known/supported currently. + if (StaticLocalLinkage == GVA_StrongODR || + StaticLocalLinkage == GVA_AvailableExternally) + return GVA_DiscardableODR; + return StaticLocalLinkage; } // MSVC treats in-class initialized static data members as definitions. @@ -9002,10 +9096,12 @@ 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++. - return !isDiscardableGVALinkage(GetGVALinkageForFunction(FD)); + return !isDiscardableGVALinkage(Linkage); } const VarDecl *VD = cast<VarDecl>(D); @@ -9357,10 +9453,8 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) { if (!NodeOrVector.template is<ASTContext::ParentVector *>()) { auto *Vector = new ASTContext::ParentVector( 1, getSingleDynTypedNodeFromParentMap(NodeOrVector)); - if (auto *Node = - NodeOrVector - .template dyn_cast<ast_type_traits::DynTypedNode *>()) - delete Node; + delete NodeOrVector + .template dyn_cast<ast_type_traits::DynTypedNode *>(); NodeOrVector = Vector; } @@ -9488,6 +9582,13 @@ uint64_t ASTContext::getTargetNullPointerValue(QualType QT) const { return getTargetInfo().getNullPointerValue(AS); } +unsigned ASTContext::getTargetAddressSpace(unsigned AS) const { + if (AS >= LangAS::FirstTargetAddressSpace) + return AS - LangAS::FirstTargetAddressSpace; + else + return (*AddrSpaceMap)[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 03e6115..b43c28d 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp @@ -360,6 +360,7 @@ void clang::FormatASTNodeDiagnosticArgument( Modifier = StringRef(); Argument = StringRef(); // Fall through + LLVM_FALLTHROUGH; } case DiagnosticsEngine::ak_qualtype: { assert(Modifier.empty() && Argument.empty() && diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp index 62261cc..92ed7da 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp @@ -102,22 +102,26 @@ namespace { /// Pending[i] is an action to dump an entity at level i. llvm::SmallVector<std::function<void(bool isLastChild)>, 32> Pending; + /// Indicates whether we should trigger deserialization of nodes that had + /// not already been loaded. + bool Deserialize = false; + /// Indicates whether we're at the top level. - bool TopLevel; + bool TopLevel = true; /// Indicates if we're handling the first child after entering a new depth. - bool FirstChild; + bool FirstChild = true; /// Prefix for currently-being-dumped entity. std::string Prefix; /// Keep track of the last location we print out so that we can /// print out deltas from then on out. - const char *LastLocFilename; - unsigned LastLocLine; + const char *LastLocFilename = ""; + unsigned LastLocLine = ~0U; /// The \c FullComment parent of the comment being dumped. - const FullComment *FC; + const FullComment *FC = nullptr; bool ShowColors; @@ -203,15 +207,14 @@ namespace { public: ASTDumper(raw_ostream &OS, const CommandTraits *Traits, const SourceManager *SM) - : OS(OS), Traits(Traits), SM(SM), TopLevel(true), FirstChild(true), - LastLocFilename(""), LastLocLine(~0U), FC(nullptr), + : OS(OS), Traits(Traits), SM(SM), ShowColors(SM && SM->getDiagnostics().getShowColors()) { } ASTDumper(raw_ostream &OS, const CommandTraits *Traits, const SourceManager *SM, bool ShowColors) - : OS(OS), Traits(Traits), SM(SM), TopLevel(true), FirstChild(true), - LastLocFilename(""), LastLocLine(~0U), - ShowColors(ShowColors) { } + : OS(OS), Traits(Traits), SM(SM), ShowColors(ShowColors) {} + + void setDeserialize(bool D) { Deserialize = D; } void dumpDecl(const Decl *D); void dumpStmt(const Stmt *S); @@ -764,14 +767,15 @@ bool ASTDumper::hasNodes(const DeclContext *DC) { return false; return DC->hasExternalLexicalStorage() || - DC->noload_decls_begin() != DC->noload_decls_end(); + (Deserialize ? DC->decls_begin() != DC->decls_end() + : DC->noload_decls_begin() != DC->noload_decls_end()); } void ASTDumper::dumpDeclContext(const DeclContext *DC) { if (!DC) return; - for (auto *D : DC->noload_decls()) + for (auto *D : (Deserialize ? DC->decls() : DC->noload_decls())) dumpDecl(D); if (DC->hasExternalLexicalStorage()) { @@ -795,11 +799,13 @@ void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) { bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage(); - DeclContext::all_lookups_iterator I = Primary->noload_lookups_begin(), - E = Primary->noload_lookups_end(); - while (I != E) { + for (auto I = Deserialize ? Primary->lookups_begin() + : Primary->noload_lookups_begin(), + E = Deserialize ? Primary->lookups_end() + : Primary->noload_lookups_end(); + I != E; ++I) { DeclarationName Name = I.getLookupName(); - DeclContextLookupResult R = *I++; + DeclContextLookupResult R = *I; dumpChild([=] { OS << "DeclarationName "; @@ -1032,10 +1038,10 @@ void ASTDumper::dumpDecl(const Decl *D) { dumpSourceRange(D->getSourceRange()); OS << ' '; dumpLocation(D->getLocation()); - if (Module *M = D->getImportedOwningModule()) + if (D->isFromASTFile()) + OS << " imported"; + if (Module *M = D->getOwningModule()) OS << " in " << M->getFullModuleName(); - else if (Module *M = D->getLocalOwningModule()) - OS << " in (local) " << M->getFullModuleName(); if (auto *ND = dyn_cast<NamedDecl>(D)) for (Module *M : D->getASTContext().getModulesWithMergedDefinition( const_cast<NamedDecl *>(ND))) @@ -1178,6 +1184,27 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { I != E; ++I) dumpCXXCtorInitializer(*I); + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) + if (MD->size_overridden_methods() != 0) { + auto dumpOverride = + [=](const CXXMethodDecl *D) { + SplitQualType T_split = D->getType().split(); + OS << D << " " << D->getParent()->getName() << "::" + << D->getNameAsString() << " '" << QualType::getAsString(T_split) << "'"; + }; + + dumpChild([=] { + auto FirstOverrideItr = MD->begin_overridden_methods(); + OS << "Overrides: [ "; + dumpOverride(*FirstOverrideItr); + for (const auto *Override : + llvm::make_range(FirstOverrideItr + 1, + MD->end_overridden_methods())) + dumpOverride(Override); + OS << " ]"; + }); + } + if (D->doesThisDeclarationHaveABody()) dumpStmt(D->getBody()); } @@ -1463,6 +1490,7 @@ void ASTDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { OS << " typename"; else OS << " class"; + OS << " depth " << D->getDepth() << " index " << D->getIndex(); if (D->isParameterPack()) OS << " ..."; dumpName(D); @@ -1472,6 +1500,7 @@ void ASTDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { void ASTDumper::VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) { dumpType(D->getType()); + OS << " depth " << D->getDepth() << " index " << D->getIndex(); if (D->isParameterPack()) OS << " ..."; dumpName(D); @@ -1481,6 +1510,7 @@ void ASTDumper::VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) { void ASTDumper::VisitTemplateTemplateParmDecl( const TemplateTemplateParmDecl *D) { + OS << " depth " << D->getDepth() << " index " << D->getIndex(); if (D->isParameterPack()) OS << " ..."; dumpName(D); @@ -2504,9 +2534,10 @@ LLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS) const { LLVM_DUMP_METHOD void Decl::dump() const { dump(llvm::errs()); } -LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS) const { +LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS, bool Deserialize) const { ASTDumper P(OS, &getASTContext().getCommentCommandTraits(), &getASTContext().getSourceManager()); + P.setDeserialize(Deserialize); P.dumpDecl(this); } @@ -2521,12 +2552,14 @@ LLVM_DUMP_METHOD void DeclContext::dumpLookups() const { } LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS, - bool DumpDecls) const { + bool DumpDecls, + bool Deserialize) const { const DeclContext *DC = this; while (!DC->isTranslationUnit()) DC = DC->getParent(); ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext(); ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &Ctx.getSourceManager()); + P.setDeserialize(Deserialize); P.dumpLookups(this, DumpDecls); } diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp index 1ccb746..2c0bb11 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp @@ -14,6 +14,7 @@ #include "clang/AST/ASTImporter.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" +#include "clang/AST/ASTStructuralEquivalence.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclVisitor.h" @@ -72,7 +73,7 @@ namespace clang { QualType VisitEnumType(const EnumType *T); QualType VisitAttributedType(const AttributedType *T); QualType VisitTemplateTypeParmType(const TemplateTypeParmType *T); - // FIXME: SubstTemplateTypeParmType + QualType VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T); QualType VisitTemplateSpecializationType(const TemplateSpecializationType *T); QualType VisitElaboratedType(const ElaboratedType *T); // FIXME: DependentNameType @@ -278,6 +279,8 @@ namespace clang { Expr *VisitArrayInitIndexExpr(ArrayInitIndexExpr *E); Expr *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E); Expr *VisitCXXNamedCastExpr(CXXNamedCastExpr *E); + Expr *VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E); + template<typename IIter, typename OIter> void ImportArray(IIter Ibegin, IIter Iend, OIter Obegin) { @@ -316,1287 +319,18 @@ namespace clang { bool ImportArrayChecked(const InContainerTy &InContainer, OIter Obegin) { return ImportArrayChecked(InContainer.begin(), InContainer.end(), Obegin); } - }; -} - -using namespace clang; - -//---------------------------------------------------------------------------- -// Structural Equivalence -//---------------------------------------------------------------------------- - -namespace { - struct StructuralEquivalenceContext { - /// \brief AST contexts for which we are checking structural equivalence. - ASTContext &C1, &C2; - - /// \brief The set of "tentative" equivalences between two canonical - /// declarations, mapping from a declaration in the first context to the - /// declaration in the second context that we believe to be equivalent. - llvm::DenseMap<Decl *, Decl *> TentativeEquivalences; - - /// \brief Queue of declarations in the first context whose equivalence - /// with a declaration in the second context still needs to be verified. - std::deque<Decl *> DeclsToCheck; - - /// \brief Declaration (from, to) pairs that are known not to be equivalent - /// (which we have already complained about). - llvm::DenseSet<std::pair<Decl *, Decl *> > &NonEquivalentDecls; - - /// \brief Whether we're being strict about the spelling of types when - /// unifying two types. - bool StrictTypeSpelling; - - /// \brief Whether to complain about failures. - bool Complain; - - /// \brief \c true if the last diagnostic came from C2. - bool LastDiagFromC2; - - StructuralEquivalenceContext(ASTContext &C1, ASTContext &C2, - llvm::DenseSet<std::pair<Decl *, Decl *> > &NonEquivalentDecls, - bool StrictTypeSpelling = false, - bool Complain = true) - : C1(C1), C2(C2), NonEquivalentDecls(NonEquivalentDecls), - StrictTypeSpelling(StrictTypeSpelling), Complain(Complain), - LastDiagFromC2(false) {} - - /// \brief Determine whether the two declarations are structurally - /// equivalent. - bool IsStructurallyEquivalent(Decl *D1, Decl *D2); - - /// \brief Determine whether the two types are structurally equivalent. - bool IsStructurallyEquivalent(QualType T1, QualType T2); - - private: - /// \brief Finish checking all of the structural equivalences. - /// - /// \returns true if an error occurred, false otherwise. - bool Finish(); - - public: - DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID) { - assert(Complain && "Not allowed to complain"); - if (LastDiagFromC2) - C1.getDiagnostics().notePriorDiagnosticFrom(C2.getDiagnostics()); - LastDiagFromC2 = false; - return C1.getDiagnostics().Report(Loc, DiagID); - } - DiagnosticBuilder Diag2(SourceLocation Loc, unsigned DiagID) { - assert(Complain && "Not allowed to complain"); - if (!LastDiagFromC2) - C2.getDiagnostics().notePriorDiagnosticFrom(C1.getDiagnostics()); - LastDiagFromC2 = true; - return C2.getDiagnostics().Report(Loc, DiagID); - } + // Importing overrides. + void ImportOverrides(CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod); }; } -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - QualType T1, QualType T2); -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - Decl *D1, Decl *D2); - -/// \brief Determine structural equivalence of two expressions. -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - Expr *E1, Expr *E2) { - if (!E1 || !E2) - return E1 == E2; - - // FIXME: Actually perform a structural comparison! - return true; -} - -/// \brief Determine whether two identifiers are equivalent. -static bool IsStructurallyEquivalent(const IdentifierInfo *Name1, - const IdentifierInfo *Name2) { - if (!Name1 || !Name2) - return Name1 == Name2; - - return Name1->getName() == Name2->getName(); -} - -/// \brief Determine whether two nested-name-specifiers are equivalent. -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - NestedNameSpecifier *NNS1, - NestedNameSpecifier *NNS2) { - // FIXME: Implement! - return true; -} - -/// \brief Determine whether two template arguments are equivalent. -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - const TemplateArgument &Arg1, - const TemplateArgument &Arg2) { - if (Arg1.getKind() != Arg2.getKind()) - return false; - - switch (Arg1.getKind()) { - case TemplateArgument::Null: - return true; - - case TemplateArgument::Type: - return Context.IsStructurallyEquivalent(Arg1.getAsType(), Arg2.getAsType()); - - case TemplateArgument::Integral: - if (!Context.IsStructurallyEquivalent(Arg1.getIntegralType(), - Arg2.getIntegralType())) - return false; - - return llvm::APSInt::isSameValue(Arg1.getAsIntegral(), Arg2.getAsIntegral()); - - case TemplateArgument::Declaration: - return Context.IsStructurallyEquivalent(Arg1.getAsDecl(), Arg2.getAsDecl()); - - case TemplateArgument::NullPtr: - return true; // FIXME: Is this correct? - - case TemplateArgument::Template: - return IsStructurallyEquivalent(Context, - Arg1.getAsTemplate(), - Arg2.getAsTemplate()); - - case TemplateArgument::TemplateExpansion: - return IsStructurallyEquivalent(Context, - Arg1.getAsTemplateOrTemplatePattern(), - Arg2.getAsTemplateOrTemplatePattern()); - - case TemplateArgument::Expression: - return IsStructurallyEquivalent(Context, - Arg1.getAsExpr(), Arg2.getAsExpr()); - - case TemplateArgument::Pack: - if (Arg1.pack_size() != Arg2.pack_size()) - return false; - - for (unsigned I = 0, N = Arg1.pack_size(); I != N; ++I) - if (!IsStructurallyEquivalent(Context, - Arg1.pack_begin()[I], - Arg2.pack_begin()[I])) - return false; - - return true; - } - - llvm_unreachable("Invalid template argument kind"); -} - -/// \brief Determine structural equivalence for the common part of array -/// types. -static bool IsArrayStructurallyEquivalent(StructuralEquivalenceContext &Context, - const ArrayType *Array1, - const ArrayType *Array2) { - if (!IsStructurallyEquivalent(Context, - Array1->getElementType(), - Array2->getElementType())) - return false; - if (Array1->getSizeModifier() != Array2->getSizeModifier()) - return false; - if (Array1->getIndexTypeQualifiers() != Array2->getIndexTypeQualifiers()) - return false; - - return true; -} - -/// \brief Determine structural equivalence of two types. -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - QualType T1, QualType T2) { - if (T1.isNull() || T2.isNull()) - return T1.isNull() && T2.isNull(); - - if (!Context.StrictTypeSpelling) { - // We aren't being strict about token-to-token equivalence of types, - // so map down to the canonical type. - T1 = Context.C1.getCanonicalType(T1); - T2 = Context.C2.getCanonicalType(T2); - } - - if (T1.getQualifiers() != T2.getQualifiers()) - return false; - - Type::TypeClass TC = T1->getTypeClass(); - - if (T1->getTypeClass() != T2->getTypeClass()) { - // Compare function types with prototypes vs. without prototypes as if - // both did not have prototypes. - if (T1->getTypeClass() == Type::FunctionProto && - T2->getTypeClass() == Type::FunctionNoProto) - TC = Type::FunctionNoProto; - else if (T1->getTypeClass() == Type::FunctionNoProto && - T2->getTypeClass() == Type::FunctionProto) - TC = Type::FunctionNoProto; - else - return false; - } - - switch (TC) { - case Type::Builtin: - // FIXME: Deal with Char_S/Char_U. - if (cast<BuiltinType>(T1)->getKind() != cast<BuiltinType>(T2)->getKind()) - return false; - break; - - case Type::Complex: - if (!IsStructurallyEquivalent(Context, - cast<ComplexType>(T1)->getElementType(), - cast<ComplexType>(T2)->getElementType())) - return false; - break; - - case Type::Adjusted: - case Type::Decayed: - if (!IsStructurallyEquivalent(Context, - cast<AdjustedType>(T1)->getOriginalType(), - cast<AdjustedType>(T2)->getOriginalType())) - return false; - break; - - case Type::Pointer: - if (!IsStructurallyEquivalent(Context, - cast<PointerType>(T1)->getPointeeType(), - cast<PointerType>(T2)->getPointeeType())) - return false; - break; - - case Type::BlockPointer: - if (!IsStructurallyEquivalent(Context, - cast<BlockPointerType>(T1)->getPointeeType(), - cast<BlockPointerType>(T2)->getPointeeType())) - return false; - break; - - case Type::LValueReference: - case Type::RValueReference: { - const ReferenceType *Ref1 = cast<ReferenceType>(T1); - const ReferenceType *Ref2 = cast<ReferenceType>(T2); - if (Ref1->isSpelledAsLValue() != Ref2->isSpelledAsLValue()) - return false; - if (Ref1->isInnerRef() != Ref2->isInnerRef()) - return false; - if (!IsStructurallyEquivalent(Context, - Ref1->getPointeeTypeAsWritten(), - Ref2->getPointeeTypeAsWritten())) - return false; - break; - } - - case Type::MemberPointer: { - const MemberPointerType *MemPtr1 = cast<MemberPointerType>(T1); - const MemberPointerType *MemPtr2 = cast<MemberPointerType>(T2); - if (!IsStructurallyEquivalent(Context, - MemPtr1->getPointeeType(), - MemPtr2->getPointeeType())) - return false; - if (!IsStructurallyEquivalent(Context, - QualType(MemPtr1->getClass(), 0), - QualType(MemPtr2->getClass(), 0))) - return false; - break; - } - - case Type::ConstantArray: { - const ConstantArrayType *Array1 = cast<ConstantArrayType>(T1); - const ConstantArrayType *Array2 = cast<ConstantArrayType>(T2); - if (!llvm::APInt::isSameValue(Array1->getSize(), Array2->getSize())) - return false; - - if (!IsArrayStructurallyEquivalent(Context, Array1, Array2)) - return false; - break; - } - - case Type::IncompleteArray: - if (!IsArrayStructurallyEquivalent(Context, - cast<ArrayType>(T1), - cast<ArrayType>(T2))) - return false; - break; - - case Type::VariableArray: { - const VariableArrayType *Array1 = cast<VariableArrayType>(T1); - const VariableArrayType *Array2 = cast<VariableArrayType>(T2); - if (!IsStructurallyEquivalent(Context, - Array1->getSizeExpr(), Array2->getSizeExpr())) - return false; - - if (!IsArrayStructurallyEquivalent(Context, Array1, Array2)) - return false; - - break; - } - - case Type::DependentSizedArray: { - const DependentSizedArrayType *Array1 = cast<DependentSizedArrayType>(T1); - const DependentSizedArrayType *Array2 = cast<DependentSizedArrayType>(T2); - if (!IsStructurallyEquivalent(Context, - Array1->getSizeExpr(), Array2->getSizeExpr())) - return false; - - if (!IsArrayStructurallyEquivalent(Context, Array1, Array2)) - return false; - - break; - } - - case Type::DependentSizedExtVector: { - const DependentSizedExtVectorType *Vec1 - = cast<DependentSizedExtVectorType>(T1); - const DependentSizedExtVectorType *Vec2 - = cast<DependentSizedExtVectorType>(T2); - if (!IsStructurallyEquivalent(Context, - Vec1->getSizeExpr(), Vec2->getSizeExpr())) - return false; - if (!IsStructurallyEquivalent(Context, - Vec1->getElementType(), - Vec2->getElementType())) - return false; - break; - } - - case Type::Vector: - case Type::ExtVector: { - const VectorType *Vec1 = cast<VectorType>(T1); - const VectorType *Vec2 = cast<VectorType>(T2); - if (!IsStructurallyEquivalent(Context, - Vec1->getElementType(), - Vec2->getElementType())) - return false; - if (Vec1->getNumElements() != Vec2->getNumElements()) - return false; - if (Vec1->getVectorKind() != Vec2->getVectorKind()) - return false; - break; - } - - case Type::FunctionProto: { - const FunctionProtoType *Proto1 = cast<FunctionProtoType>(T1); - const FunctionProtoType *Proto2 = cast<FunctionProtoType>(T2); - if (Proto1->getNumParams() != Proto2->getNumParams()) - return false; - for (unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) { - if (!IsStructurallyEquivalent(Context, Proto1->getParamType(I), - Proto2->getParamType(I))) - return false; - } - if (Proto1->isVariadic() != Proto2->isVariadic()) - return false; - if (Proto1->getExceptionSpecType() != Proto2->getExceptionSpecType()) - return false; - if (Proto1->getExceptionSpecType() == EST_Dynamic) { - if (Proto1->getNumExceptions() != Proto2->getNumExceptions()) - return false; - for (unsigned I = 0, N = Proto1->getNumExceptions(); I != N; ++I) { - if (!IsStructurallyEquivalent(Context, - Proto1->getExceptionType(I), - Proto2->getExceptionType(I))) - return false; - } - } else if (Proto1->getExceptionSpecType() == EST_ComputedNoexcept) { - if (!IsStructurallyEquivalent(Context, - Proto1->getNoexceptExpr(), - Proto2->getNoexceptExpr())) - return false; - } - if (Proto1->getTypeQuals() != Proto2->getTypeQuals()) - return false; - - // Fall through to check the bits common with FunctionNoProtoType. - } - - case Type::FunctionNoProto: { - const FunctionType *Function1 = cast<FunctionType>(T1); - const FunctionType *Function2 = cast<FunctionType>(T2); - if (!IsStructurallyEquivalent(Context, Function1->getReturnType(), - Function2->getReturnType())) - return false; - if (Function1->getExtInfo() != Function2->getExtInfo()) - return false; - break; - } - - case Type::UnresolvedUsing: - if (!IsStructurallyEquivalent(Context, - cast<UnresolvedUsingType>(T1)->getDecl(), - cast<UnresolvedUsingType>(T2)->getDecl())) - return false; - - break; - - case Type::Attributed: - if (!IsStructurallyEquivalent(Context, - cast<AttributedType>(T1)->getModifiedType(), - cast<AttributedType>(T2)->getModifiedType())) - return false; - if (!IsStructurallyEquivalent(Context, - cast<AttributedType>(T1)->getEquivalentType(), - cast<AttributedType>(T2)->getEquivalentType())) - return false; - break; - - case Type::Paren: - if (!IsStructurallyEquivalent(Context, - cast<ParenType>(T1)->getInnerType(), - cast<ParenType>(T2)->getInnerType())) - return false; - break; - - case Type::Typedef: - if (!IsStructurallyEquivalent(Context, - cast<TypedefType>(T1)->getDecl(), - cast<TypedefType>(T2)->getDecl())) - return false; - break; - - case Type::TypeOfExpr: - if (!IsStructurallyEquivalent(Context, - cast<TypeOfExprType>(T1)->getUnderlyingExpr(), - cast<TypeOfExprType>(T2)->getUnderlyingExpr())) - return false; - break; - - case Type::TypeOf: - if (!IsStructurallyEquivalent(Context, - cast<TypeOfType>(T1)->getUnderlyingType(), - cast<TypeOfType>(T2)->getUnderlyingType())) - return false; - break; - - case Type::UnaryTransform: - if (!IsStructurallyEquivalent(Context, - cast<UnaryTransformType>(T1)->getUnderlyingType(), - cast<UnaryTransformType>(T1)->getUnderlyingType())) - return false; - break; - - case Type::Decltype: - if (!IsStructurallyEquivalent(Context, - cast<DecltypeType>(T1)->getUnderlyingExpr(), - cast<DecltypeType>(T2)->getUnderlyingExpr())) - return false; - break; - - case Type::Auto: - if (!IsStructurallyEquivalent(Context, - cast<AutoType>(T1)->getDeducedType(), - cast<AutoType>(T2)->getDeducedType())) - return false; - break; - - case Type::Record: - case Type::Enum: - if (!IsStructurallyEquivalent(Context, - cast<TagType>(T1)->getDecl(), - cast<TagType>(T2)->getDecl())) - return false; - break; - - case Type::TemplateTypeParm: { - const TemplateTypeParmType *Parm1 = cast<TemplateTypeParmType>(T1); - const TemplateTypeParmType *Parm2 = cast<TemplateTypeParmType>(T2); - if (Parm1->getDepth() != Parm2->getDepth()) - return false; - if (Parm1->getIndex() != Parm2->getIndex()) - return false; - if (Parm1->isParameterPack() != Parm2->isParameterPack()) - return false; - - // Names of template type parameters are never significant. - break; - } - - case Type::SubstTemplateTypeParm: { - const SubstTemplateTypeParmType *Subst1 - = cast<SubstTemplateTypeParmType>(T1); - const SubstTemplateTypeParmType *Subst2 - = cast<SubstTemplateTypeParmType>(T2); - if (!IsStructurallyEquivalent(Context, - QualType(Subst1->getReplacedParameter(), 0), - QualType(Subst2->getReplacedParameter(), 0))) - return false; - if (!IsStructurallyEquivalent(Context, - Subst1->getReplacementType(), - Subst2->getReplacementType())) - return false; - break; - } - - case Type::SubstTemplateTypeParmPack: { - const SubstTemplateTypeParmPackType *Subst1 - = cast<SubstTemplateTypeParmPackType>(T1); - const SubstTemplateTypeParmPackType *Subst2 - = cast<SubstTemplateTypeParmPackType>(T2); - if (!IsStructurallyEquivalent(Context, - QualType(Subst1->getReplacedParameter(), 0), - QualType(Subst2->getReplacedParameter(), 0))) - return false; - if (!IsStructurallyEquivalent(Context, - Subst1->getArgumentPack(), - Subst2->getArgumentPack())) - return false; - break; - } - case Type::TemplateSpecialization: { - const TemplateSpecializationType *Spec1 - = cast<TemplateSpecializationType>(T1); - const TemplateSpecializationType *Spec2 - = cast<TemplateSpecializationType>(T2); - if (!IsStructurallyEquivalent(Context, - Spec1->getTemplateName(), - Spec2->getTemplateName())) - return false; - if (Spec1->getNumArgs() != Spec2->getNumArgs()) - return false; - for (unsigned I = 0, N = Spec1->getNumArgs(); I != N; ++I) { - if (!IsStructurallyEquivalent(Context, - Spec1->getArg(I), Spec2->getArg(I))) - return false; - } - break; - } - - case Type::Elaborated: { - const ElaboratedType *Elab1 = cast<ElaboratedType>(T1); - const ElaboratedType *Elab2 = cast<ElaboratedType>(T2); - // CHECKME: what if a keyword is ETK_None or ETK_typename ? - if (Elab1->getKeyword() != Elab2->getKeyword()) - return false; - if (!IsStructurallyEquivalent(Context, - Elab1->getQualifier(), - Elab2->getQualifier())) - return false; - if (!IsStructurallyEquivalent(Context, - Elab1->getNamedType(), - Elab2->getNamedType())) - return false; - break; - } - - case Type::InjectedClassName: { - const InjectedClassNameType *Inj1 = cast<InjectedClassNameType>(T1); - const InjectedClassNameType *Inj2 = cast<InjectedClassNameType>(T2); - if (!IsStructurallyEquivalent(Context, - Inj1->getInjectedSpecializationType(), - Inj2->getInjectedSpecializationType())) - return false; - break; - } - - case Type::DependentName: { - const DependentNameType *Typename1 = cast<DependentNameType>(T1); - const DependentNameType *Typename2 = cast<DependentNameType>(T2); - if (!IsStructurallyEquivalent(Context, - Typename1->getQualifier(), - Typename2->getQualifier())) - return false; - if (!IsStructurallyEquivalent(Typename1->getIdentifier(), - Typename2->getIdentifier())) - return false; - - break; - } - - case Type::DependentTemplateSpecialization: { - const DependentTemplateSpecializationType *Spec1 = - cast<DependentTemplateSpecializationType>(T1); - const DependentTemplateSpecializationType *Spec2 = - cast<DependentTemplateSpecializationType>(T2); - if (!IsStructurallyEquivalent(Context, - Spec1->getQualifier(), - Spec2->getQualifier())) - return false; - if (!IsStructurallyEquivalent(Spec1->getIdentifier(), - Spec2->getIdentifier())) - return false; - if (Spec1->getNumArgs() != Spec2->getNumArgs()) - return false; - for (unsigned I = 0, N = Spec1->getNumArgs(); I != N; ++I) { - if (!IsStructurallyEquivalent(Context, - Spec1->getArg(I), Spec2->getArg(I))) - return false; - } - break; - } - - case Type::PackExpansion: - if (!IsStructurallyEquivalent(Context, - cast<PackExpansionType>(T1)->getPattern(), - cast<PackExpansionType>(T2)->getPattern())) - return false; - break; - - case Type::ObjCInterface: { - const ObjCInterfaceType *Iface1 = cast<ObjCInterfaceType>(T1); - const ObjCInterfaceType *Iface2 = cast<ObjCInterfaceType>(T2); - if (!IsStructurallyEquivalent(Context, - Iface1->getDecl(), Iface2->getDecl())) - return false; - 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); - if (!IsStructurallyEquivalent(Context, - Obj1->getBaseType(), - Obj2->getBaseType())) - 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::ObjCObjectPointer: { - const ObjCObjectPointerType *Ptr1 = cast<ObjCObjectPointerType>(T1); - const ObjCObjectPointerType *Ptr2 = cast<ObjCObjectPointerType>(T2); - if (!IsStructurallyEquivalent(Context, - Ptr1->getPointeeType(), - Ptr2->getPointeeType())) - return false; - break; - } - - case Type::Atomic: { - if (!IsStructurallyEquivalent(Context, - cast<AtomicType>(T1)->getValueType(), - cast<AtomicType>(T2)->getValueType())) - return false; - break; - } - - case Type::Pipe: { - if (!IsStructurallyEquivalent(Context, - cast<PipeType>(T1)->getElementType(), - cast<PipeType>(T2)->getElementType())) - return false; - break; - } - - } // end switch - - return true; -} - -/// \brief Determine structural equivalence of two fields. -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - FieldDecl *Field1, FieldDecl *Field2) { - RecordDecl *Owner2 = cast<RecordDecl>(Field2->getDeclContext()); - - // For anonymous structs/unions, match up the anonymous struct/union type - // declarations directly, so that we don't go off searching for anonymous - // types - if (Field1->isAnonymousStructOrUnion() && - Field2->isAnonymousStructOrUnion()) { - RecordDecl *D1 = Field1->getType()->castAs<RecordType>()->getDecl(); - RecordDecl *D2 = Field2->getType()->castAs<RecordType>()->getDecl(); - return IsStructurallyEquivalent(Context, D1, D2); - } - - // Check for equivalent field names. - IdentifierInfo *Name1 = Field1->getIdentifier(); - IdentifierInfo *Name2 = Field2->getIdentifier(); - if (!::IsStructurallyEquivalent(Name1, Name2)) - return false; - - if (!IsStructurallyEquivalent(Context, - Field1->getType(), Field2->getType())) { - if (Context.Complain) { - Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent) - << Context.C2.getTypeDeclType(Owner2); - Context.Diag2(Field2->getLocation(), diag::note_odr_field) - << Field2->getDeclName() << Field2->getType(); - Context.Diag1(Field1->getLocation(), diag::note_odr_field) - << Field1->getDeclName() << Field1->getType(); - } - return false; - } - - if (Field1->isBitField() != Field2->isBitField()) { - if (Context.Complain) { - Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent) - << Context.C2.getTypeDeclType(Owner2); - if (Field1->isBitField()) { - Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field) - << Field1->getDeclName() << Field1->getType() - << Field1->getBitWidthValue(Context.C1); - Context.Diag2(Field2->getLocation(), diag::note_odr_not_bit_field) - << Field2->getDeclName(); - } else { - Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field) - << Field2->getDeclName() << Field2->getType() - << Field2->getBitWidthValue(Context.C2); - Context.Diag1(Field1->getLocation(), diag::note_odr_not_bit_field) - << Field1->getDeclName(); - } - } - return false; - } - - if (Field1->isBitField()) { - // Make sure that the bit-fields are the same length. - unsigned Bits1 = Field1->getBitWidthValue(Context.C1); - unsigned Bits2 = Field2->getBitWidthValue(Context.C2); - - if (Bits1 != Bits2) { - if (Context.Complain) { - Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent) - << Context.C2.getTypeDeclType(Owner2); - Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field) - << Field2->getDeclName() << Field2->getType() << Bits2; - Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field) - << Field1->getDeclName() << Field1->getType() << Bits1; - } - return false; - } - } - - return true; -} - -/// \brief Find the index of the given anonymous struct/union within its -/// context. -/// -/// \returns Returns the index of this anonymous struct/union in its context, -/// including the next assigned index (if none of them match). Returns an -/// empty option if the context is not a record, i.e.. if the anonymous -/// struct/union is at namespace or block scope. -static Optional<unsigned> findUntaggedStructOrUnionIndex(RecordDecl *Anon) { - ASTContext &Context = Anon->getASTContext(); - QualType AnonTy = Context.getRecordType(Anon); - - RecordDecl *Owner = dyn_cast<RecordDecl>(Anon->getDeclContext()); - if (!Owner) - return None; - - unsigned Index = 0; - for (const auto *D : Owner->noload_decls()) { - const auto *F = dyn_cast<FieldDecl>(D); - if (!F) - continue; - - if (F->isAnonymousStructOrUnion()) { - if (Context.hasSameType(F->getType(), AnonTy)) - break; - ++Index; - continue; - } - - // If the field looks like this: - // struct { ... } A; - QualType FieldType = F->getType(); - if (const auto *RecType = dyn_cast<RecordType>(FieldType)) { - const RecordDecl *RecDecl = RecType->getDecl(); - if (RecDecl->getDeclContext() == Owner && - !RecDecl->getIdentifier()) { - if (Context.hasSameType(FieldType, AnonTy)) - break; - ++Index; - continue; - } - } - } - - return Index; -} - -/// \brief Determine structural equivalence of two records. -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - RecordDecl *D1, RecordDecl *D2) { - if (D1->isUnion() != D2->isUnion()) { - if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) - << Context.C2.getTypeDeclType(D2); - Context.Diag1(D1->getLocation(), diag::note_odr_tag_kind_here) - << D1->getDeclName() << (unsigned)D1->getTagKind(); - } - return false; - } - - if (D1->isAnonymousStructOrUnion() && D2->isAnonymousStructOrUnion()) { - // If both anonymous structs/unions are in a record context, make sure - // they occur in the same location in the context records. - if (Optional<unsigned> Index1 = findUntaggedStructOrUnionIndex(D1)) { - if (Optional<unsigned> Index2 = findUntaggedStructOrUnionIndex(D2)) { - if (*Index1 != *Index2) - return false; - } - } - } - - // If both declarations are class template specializations, we know - // the ODR applies, so check the template and template arguments. - ClassTemplateSpecializationDecl *Spec1 - = dyn_cast<ClassTemplateSpecializationDecl>(D1); - ClassTemplateSpecializationDecl *Spec2 - = dyn_cast<ClassTemplateSpecializationDecl>(D2); - if (Spec1 && Spec2) { - // Check that the specialized templates are the same. - if (!IsStructurallyEquivalent(Context, Spec1->getSpecializedTemplate(), - Spec2->getSpecializedTemplate())) - return false; - - // Check that the template arguments are the same. - if (Spec1->getTemplateArgs().size() != Spec2->getTemplateArgs().size()) - return false; - - for (unsigned I = 0, N = Spec1->getTemplateArgs().size(); I != N; ++I) - if (!IsStructurallyEquivalent(Context, - Spec1->getTemplateArgs().get(I), - Spec2->getTemplateArgs().get(I))) - return false; - } - // If one is a class template specialization and the other is not, these - // structures are different. - else if (Spec1 || Spec2) - return false; - - // Compare the definitions of these two records. If either or both are - // incomplete, we assume that they are equivalent. - D1 = D1->getDefinition(); - D2 = D2->getDefinition(); - if (!D1 || !D2) - return true; - - if (CXXRecordDecl *D1CXX = dyn_cast<CXXRecordDecl>(D1)) { - if (CXXRecordDecl *D2CXX = dyn_cast<CXXRecordDecl>(D2)) { - if (D1CXX->getNumBases() != D2CXX->getNumBases()) { - if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) - << Context.C2.getTypeDeclType(D2); - Context.Diag2(D2->getLocation(), diag::note_odr_number_of_bases) - << D2CXX->getNumBases(); - Context.Diag1(D1->getLocation(), diag::note_odr_number_of_bases) - << D1CXX->getNumBases(); - } - return false; - } - - // Check the base classes. - for (CXXRecordDecl::base_class_iterator Base1 = D1CXX->bases_begin(), - BaseEnd1 = D1CXX->bases_end(), - Base2 = D2CXX->bases_begin(); - Base1 != BaseEnd1; - ++Base1, ++Base2) { - if (!IsStructurallyEquivalent(Context, - Base1->getType(), Base2->getType())) { - if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) - << Context.C2.getTypeDeclType(D2); - Context.Diag2(Base2->getLocStart(), diag::note_odr_base) - << Base2->getType() - << Base2->getSourceRange(); - Context.Diag1(Base1->getLocStart(), diag::note_odr_base) - << Base1->getType() - << Base1->getSourceRange(); - } - return false; - } - - // Check virtual vs. non-virtual inheritance mismatch. - if (Base1->isVirtual() != Base2->isVirtual()) { - if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) - << Context.C2.getTypeDeclType(D2); - Context.Diag2(Base2->getLocStart(), - diag::note_odr_virtual_base) - << Base2->isVirtual() << Base2->getSourceRange(); - Context.Diag1(Base1->getLocStart(), diag::note_odr_base) - << Base1->isVirtual() - << Base1->getSourceRange(); - } - return false; - } - } - } else if (D1CXX->getNumBases() > 0) { - if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) - << Context.C2.getTypeDeclType(D2); - const CXXBaseSpecifier *Base1 = D1CXX->bases_begin(); - Context.Diag1(Base1->getLocStart(), diag::note_odr_base) - << Base1->getType() - << Base1->getSourceRange(); - Context.Diag2(D2->getLocation(), diag::note_odr_missing_base); - } - return false; - } - } - - // Check the fields for consistency. - RecordDecl::field_iterator Field2 = D2->field_begin(), - Field2End = D2->field_end(); - for (RecordDecl::field_iterator Field1 = D1->field_begin(), - Field1End = D1->field_end(); - Field1 != Field1End; - ++Field1, ++Field2) { - if (Field2 == Field2End) { - if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) - << Context.C2.getTypeDeclType(D2); - Context.Diag1(Field1->getLocation(), diag::note_odr_field) - << Field1->getDeclName() << Field1->getType(); - Context.Diag2(D2->getLocation(), diag::note_odr_missing_field); - } - return false; - } - - if (!IsStructurallyEquivalent(Context, *Field1, *Field2)) - return false; - } - - if (Field2 != Field2End) { - if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) - << Context.C2.getTypeDeclType(D2); - Context.Diag2(Field2->getLocation(), diag::note_odr_field) - << Field2->getDeclName() << Field2->getType(); - Context.Diag1(D1->getLocation(), diag::note_odr_missing_field); - } - return false; - } - - return true; -} - -/// \brief Determine structural equivalence of two enums. -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - EnumDecl *D1, EnumDecl *D2) { - EnumDecl::enumerator_iterator EC2 = D2->enumerator_begin(), - EC2End = D2->enumerator_end(); - for (EnumDecl::enumerator_iterator EC1 = D1->enumerator_begin(), - EC1End = D1->enumerator_end(); - EC1 != EC1End; ++EC1, ++EC2) { - if (EC2 == EC2End) { - if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) - << Context.C2.getTypeDeclType(D2); - Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator) - << EC1->getDeclName() - << EC1->getInitVal().toString(10); - Context.Diag2(D2->getLocation(), diag::note_odr_missing_enumerator); - } - return false; - } - - llvm::APSInt Val1 = EC1->getInitVal(); - llvm::APSInt Val2 = EC2->getInitVal(); - if (!llvm::APSInt::isSameValue(Val1, Val2) || - !IsStructurallyEquivalent(EC1->getIdentifier(), EC2->getIdentifier())) { - if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) - << Context.C2.getTypeDeclType(D2); - Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator) - << EC2->getDeclName() - << EC2->getInitVal().toString(10); - Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator) - << EC1->getDeclName() - << EC1->getInitVal().toString(10); - } - return false; - } - } - - if (EC2 != EC2End) { - if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) - << Context.C2.getTypeDeclType(D2); - Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator) - << EC2->getDeclName() - << EC2->getInitVal().toString(10); - Context.Diag1(D1->getLocation(), diag::note_odr_missing_enumerator); - } - return false; - } - - return true; -} - -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - TemplateParameterList *Params1, - TemplateParameterList *Params2) { - if (Params1->size() != Params2->size()) { - if (Context.Complain) { - Context.Diag2(Params2->getTemplateLoc(), - diag::err_odr_different_num_template_parameters) - << Params1->size() << Params2->size(); - Context.Diag1(Params1->getTemplateLoc(), - diag::note_odr_template_parameter_list); - } - return false; - } - - for (unsigned I = 0, N = Params1->size(); I != N; ++I) { - if (Params1->getParam(I)->getKind() != Params2->getParam(I)->getKind()) { - if (Context.Complain) { - Context.Diag2(Params2->getParam(I)->getLocation(), - diag::err_odr_different_template_parameter_kind); - Context.Diag1(Params1->getParam(I)->getLocation(), - diag::note_odr_template_parameter_here); - } - return false; - } - - if (!Context.IsStructurallyEquivalent(Params1->getParam(I), - Params2->getParam(I))) { - - return false; - } - } - - return true; -} - -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - TemplateTypeParmDecl *D1, - TemplateTypeParmDecl *D2) { - if (D1->isParameterPack() != D2->isParameterPack()) { - if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack) - << D2->isParameterPack(); - Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack) - << D1->isParameterPack(); - } - return false; - } - - return true; -} - -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - NonTypeTemplateParmDecl *D1, - NonTypeTemplateParmDecl *D2) { - if (D1->isParameterPack() != D2->isParameterPack()) { - if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack) - << D2->isParameterPack(); - Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack) - << D1->isParameterPack(); - } - return false; - } - - // Check types. - if (!Context.IsStructurallyEquivalent(D1->getType(), D2->getType())) { - if (Context.Complain) { - Context.Diag2(D2->getLocation(), - diag::err_odr_non_type_parameter_type_inconsistent) - << D2->getType() << D1->getType(); - Context.Diag1(D1->getLocation(), diag::note_odr_value_here) - << D1->getType(); - } - return false; - } - - return true; -} - -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - TemplateTemplateParmDecl *D1, - TemplateTemplateParmDecl *D2) { - if (D1->isParameterPack() != D2->isParameterPack()) { - if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack) - << D2->isParameterPack(); - Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack) - << D1->isParameterPack(); - } - return false; - } - - // Check template parameter lists. - return IsStructurallyEquivalent(Context, D1->getTemplateParameters(), - D2->getTemplateParameters()); -} - -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - ClassTemplateDecl *D1, - ClassTemplateDecl *D2) { - // Check template parameters. - if (!IsStructurallyEquivalent(Context, - D1->getTemplateParameters(), - D2->getTemplateParameters())) - return false; - - // Check the templated declaration. - return Context.IsStructurallyEquivalent(D1->getTemplatedDecl(), - D2->getTemplatedDecl()); -} - -/// \brief Determine structural equivalence of two declarations. -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - Decl *D1, Decl *D2) { - // FIXME: Check for known structural equivalences via a callback of some sort. - - // Check whether we already know that these two declarations are not - // structurally equivalent. - if (Context.NonEquivalentDecls.count(std::make_pair(D1->getCanonicalDecl(), - D2->getCanonicalDecl()))) - return false; - - // Determine whether we've already produced a tentative equivalence for D1. - Decl *&EquivToD1 = Context.TentativeEquivalences[D1->getCanonicalDecl()]; - if (EquivToD1) - return EquivToD1 == D2->getCanonicalDecl(); - - // Produce a tentative equivalence D1 <-> D2, which will be checked later. - EquivToD1 = D2->getCanonicalDecl(); - Context.DeclsToCheck.push_back(D1->getCanonicalDecl()); - return true; -} - -bool StructuralEquivalenceContext::IsStructurallyEquivalent(Decl *D1, - Decl *D2) { - if (!::IsStructurallyEquivalent(*this, D1, D2)) - return false; - - return !Finish(); -} - -bool StructuralEquivalenceContext::IsStructurallyEquivalent(QualType T1, - QualType T2) { - if (!::IsStructurallyEquivalent(*this, T1, T2)) - return false; - - return !Finish(); -} - -bool StructuralEquivalenceContext::Finish() { - while (!DeclsToCheck.empty()) { - // Check the next declaration. - Decl *D1 = DeclsToCheck.front(); - DeclsToCheck.pop_front(); - - Decl *D2 = TentativeEquivalences[D1]; - assert(D2 && "Unrecorded tentative equivalence?"); - - bool Equivalent = true; - - // FIXME: Switch on all declaration kinds. For now, we're just going to - // check the obvious ones. - if (RecordDecl *Record1 = dyn_cast<RecordDecl>(D1)) { - if (RecordDecl *Record2 = dyn_cast<RecordDecl>(D2)) { - // Check for equivalent structure names. - IdentifierInfo *Name1 = Record1->getIdentifier(); - if (!Name1 && Record1->getTypedefNameForAnonDecl()) - Name1 = Record1->getTypedefNameForAnonDecl()->getIdentifier(); - IdentifierInfo *Name2 = Record2->getIdentifier(); - if (!Name2 && Record2->getTypedefNameForAnonDecl()) - Name2 = Record2->getTypedefNameForAnonDecl()->getIdentifier(); - if (!::IsStructurallyEquivalent(Name1, Name2) || - !::IsStructurallyEquivalent(*this, Record1, Record2)) - Equivalent = false; - } else { - // Record/non-record mismatch. - Equivalent = false; - } - } else if (EnumDecl *Enum1 = dyn_cast<EnumDecl>(D1)) { - if (EnumDecl *Enum2 = dyn_cast<EnumDecl>(D2)) { - // Check for equivalent enum names. - IdentifierInfo *Name1 = Enum1->getIdentifier(); - if (!Name1 && Enum1->getTypedefNameForAnonDecl()) - Name1 = Enum1->getTypedefNameForAnonDecl()->getIdentifier(); - IdentifierInfo *Name2 = Enum2->getIdentifier(); - if (!Name2 && Enum2->getTypedefNameForAnonDecl()) - Name2 = Enum2->getTypedefNameForAnonDecl()->getIdentifier(); - if (!::IsStructurallyEquivalent(Name1, Name2) || - !::IsStructurallyEquivalent(*this, Enum1, Enum2)) - Equivalent = false; - } else { - // Enum/non-enum mismatch - Equivalent = false; - } - } else if (TypedefNameDecl *Typedef1 = dyn_cast<TypedefNameDecl>(D1)) { - if (TypedefNameDecl *Typedef2 = dyn_cast<TypedefNameDecl>(D2)) { - if (!::IsStructurallyEquivalent(Typedef1->getIdentifier(), - Typedef2->getIdentifier()) || - !::IsStructurallyEquivalent(*this, - Typedef1->getUnderlyingType(), - Typedef2->getUnderlyingType())) - Equivalent = false; - } else { - // Typedef/non-typedef mismatch. - Equivalent = false; - } - } else if (ClassTemplateDecl *ClassTemplate1 - = dyn_cast<ClassTemplateDecl>(D1)) { - if (ClassTemplateDecl *ClassTemplate2 = dyn_cast<ClassTemplateDecl>(D2)) { - if (!::IsStructurallyEquivalent(ClassTemplate1->getIdentifier(), - ClassTemplate2->getIdentifier()) || - !::IsStructurallyEquivalent(*this, ClassTemplate1, ClassTemplate2)) - Equivalent = false; - } else { - // Class template/non-class-template mismatch. - Equivalent = false; - } - } else if (TemplateTypeParmDecl *TTP1= dyn_cast<TemplateTypeParmDecl>(D1)) { - if (TemplateTypeParmDecl *TTP2 = dyn_cast<TemplateTypeParmDecl>(D2)) { - if (!::IsStructurallyEquivalent(*this, TTP1, TTP2)) - Equivalent = false; - } else { - // Kind mismatch. - Equivalent = false; - } - } else if (NonTypeTemplateParmDecl *NTTP1 - = dyn_cast<NonTypeTemplateParmDecl>(D1)) { - if (NonTypeTemplateParmDecl *NTTP2 - = dyn_cast<NonTypeTemplateParmDecl>(D2)) { - if (!::IsStructurallyEquivalent(*this, NTTP1, NTTP2)) - Equivalent = false; - } else { - // Kind mismatch. - Equivalent = false; - } - } else if (TemplateTemplateParmDecl *TTP1 - = dyn_cast<TemplateTemplateParmDecl>(D1)) { - if (TemplateTemplateParmDecl *TTP2 - = dyn_cast<TemplateTemplateParmDecl>(D2)) { - if (!::IsStructurallyEquivalent(*this, TTP1, TTP2)) - Equivalent = false; - } else { - // Kind mismatch. - Equivalent = false; - } - } - - if (!Equivalent) { - // Note that these two declarations are not equivalent (and we already - // know about it). - NonEquivalentDecls.insert(std::make_pair(D1->getCanonicalDecl(), - D2->getCanonicalDecl())); - return true; - } - // FIXME: Check other declaration kinds! - } - - return false; -} - //---------------------------------------------------------------------------- // Import Types //---------------------------------------------------------------------------- +using namespace clang; + QualType ASTNodeImporter::VisitType(const Type *T) { Importer.FromDiag(SourceLocation(), diag::err_unsupported_ast_node) << T->getTypeClassName(); @@ -1976,6 +710,23 @@ QualType ASTNodeImporter::VisitTemplateTypeParmType( T->getDepth(), T->getIndex(), T->isParameterPack(), ParmDecl); } +QualType ASTNodeImporter::VisitSubstTemplateTypeParmType( + const SubstTemplateTypeParmType *T) { + const TemplateTypeParmType *Replaced = + cast_or_null<TemplateTypeParmType>(Importer.Import( + QualType(T->getReplacedParameter(), 0)).getTypePtr()); + if (!Replaced) + return QualType(); + + QualType Replacement = Importer.Import(T->getReplacementType()); + if (Replacement.isNull()) + return QualType(); + Replacement = Replacement.getCanonicalType(); + + return Importer.getToContext().getSubstTemplateTypeParmType( + Replaced, Replacement); +} + QualType ASTNodeImporter::VisitTemplateSpecializationType( const TemplateSpecializationType *T) { TemplateName ToTemplate = Importer.Import(T->getTemplateName()); @@ -2133,6 +884,7 @@ ASTNodeImporter::ImportDeclarationNameLoc(const DeclarationNameInfo &From, case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: case DeclarationName::CXXUsingDirective: + case DeclarationName::CXXDeductionGuideName: return; case DeclarationName::CXXOperatorName: { @@ -2204,12 +956,16 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, ToData.HasUninitializedFields = FromData.HasUninitializedFields; ToData.HasInheritedConstructor = FromData.HasInheritedConstructor; ToData.HasInheritedAssignment = FromData.HasInheritedAssignment; + ToData.NeedOverloadResolutionForCopyConstructor + = FromData.NeedOverloadResolutionForCopyConstructor; ToData.NeedOverloadResolutionForMoveConstructor = FromData.NeedOverloadResolutionForMoveConstructor; ToData.NeedOverloadResolutionForMoveAssignment = FromData.NeedOverloadResolutionForMoveAssignment; ToData.NeedOverloadResolutionForDestructor = FromData.NeedOverloadResolutionForDestructor; + ToData.DefaultedCopyConstructorIsDeleted + = FromData.DefaultedCopyConstructorIsDeleted; ToData.DefaultedMoveConstructorIsDeleted = FromData.DefaultedMoveConstructorIsDeleted; ToData.DefaultedMoveAssignmentIsDeleted @@ -2221,6 +977,7 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, = FromData.HasConstexprNonCopyMoveConstructor; ToData.HasDefaultedDefaultConstructor = FromData.HasDefaultedDefaultConstructor; + ToData.CanPassInRegisters = FromData.CanPassInRegisters; ToData.DefaultedDefaultConstructorIsConstexpr = FromData.DefaultedDefaultConstructorIsConstexpr; ToData.HasConstexprDefaultConstructor @@ -2231,8 +988,10 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, ToData.UserProvidedDefaultConstructor = FromData.UserProvidedDefaultConstructor; ToData.DeclaredSpecialMembers = FromData.DeclaredSpecialMembers; - ToData.ImplicitCopyConstructorHasConstParam - = FromData.ImplicitCopyConstructorHasConstParam; + ToData.ImplicitCopyConstructorCanHaveConstParamForVBase + = FromData.ImplicitCopyConstructorCanHaveConstParamForVBase; + ToData.ImplicitCopyConstructorCanHaveConstParamForNonVBase + = FromData.ImplicitCopyConstructorCanHaveConstParamForNonVBase; ToData.ImplicitCopyAssignmentHasConstParam = FromData.ImplicitCopyAssignmentHasConstParam; ToData.HasDeclaredCopyConstructorWithConstParam @@ -2500,7 +1259,7 @@ bool ASTNodeImporter::IsStructuralMatch(ClassTemplateDecl *From, StructuralEquivalenceContext Ctx(Importer.getFromContext(), Importer.getToContext(), Importer.getNonEquivalentDecls()); - return Ctx.IsStructurallyEquivalent(From, To); + return Ctx.IsStructurallyEquivalent(From, To); } bool ASTNodeImporter::IsStructuralMatch(VarTemplateDecl *From, @@ -2679,10 +1438,10 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { FoundTypedef->getUnderlyingType())) return Importer.Imported(D, FoundTypedef); } - + ConflictingDecls.push_back(FoundDecls[I]); } - + if (!ConflictingDecls.empty()) { Name = Importer.HandleNameConflict(Name, DC, IDNS, ConflictingDecls.data(), @@ -2691,7 +1450,7 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { return nullptr; } } - + // Import the underlying type of this typedef; QualType T = Importer.Import(D->getUnderlyingType()); if (T.isNull()) @@ -2711,12 +1470,12 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { StartL, Loc, Name.getAsIdentifierInfo(), TInfo); - + ToTypedef->setAccess(D->getAccess()); ToTypedef->setLexicalDeclContext(LexicalDC); Importer.Imported(D, ToTypedef); LexicalDC->addDeclInternal(ToTypedef); - + return ToTypedef; } @@ -2785,7 +1544,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { if (!DC->isFunctionOrMethod() && SearchName) { SmallVector<NamedDecl *, 4> ConflictingDecls; SmallVector<NamedDecl *, 2> FoundDecls; - DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); + DC->getRedeclContext()->localUncachedLookup(SearchName, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; @@ -2871,10 +1630,18 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { // We may already have a record of the same name; try to find and match it. RecordDecl *AdoptDecl = nullptr; + RecordDecl *PrevDecl = nullptr; if (!DC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; SmallVector<NamedDecl *, 2> FoundDecls; - DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); + DC->getRedeclContext()->localUncachedLookup(SearchName, FoundDecls); + + if (!FoundDecls.empty()) { + // We're going to have to compare D against potentially conflicting Decls, so complete it. + if (D->hasExternalLexicalStorage() && !D->isCompleteDefinition()) + D->getASTContext().getExternalSource()->CompleteType(D); + } + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; @@ -2890,9 +1657,10 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { FoundRecord->isAnonymousStructOrUnion()) { // If both anonymous structs/unions are in a record context, make sure // they occur in the same location in the context records. - if (Optional<unsigned> Index1 - = findUntaggedStructOrUnionIndex(D)) { - if (Optional<unsigned> Index2 = + if (Optional<unsigned> Index1 = + StructuralEquivalenceContext::findUntaggedStructOrUnionIndex( + D)) { + if (Optional<unsigned> Index2 = StructuralEquivalenceContext:: findUntaggedStructOrUnionIndex(FoundRecord)) { if (*Index1 != *Index2) continue; @@ -2900,6 +1668,8 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { } } + PrevDecl = FoundRecord; + if (RecordDecl *FoundDef = FoundRecord->getDefinition()) { if ((SearchName && !D->isCompleteDefinition()) || (D->isCompleteDefinition() && @@ -2992,6 +1762,10 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { LexicalDC->addDeclInternal(D2); if (D->isAnonymousStructOrUnion()) D2->setAnonymousStructOrUnion(true); + if (PrevDecl) { + // FIXME: do this for all Redeclarables, not just RecordDecls. + D2->setPreviousDecl(PrevDecl); + } } Importer.Imported(D, D2); @@ -3082,7 +1856,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; - + if (FunctionDecl *FoundFunction = dyn_cast<FunctionDecl>(FoundDecls[I])) { if (FoundFunction->hasExternalFormalLinkage() && D->hasExternalFormalLinkage()) { @@ -3091,14 +1865,14 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // FIXME: Actually try to merge the body and other attributes. return Importer.Imported(D, FoundFunction); } - + // FIXME: Check for overloading more carefully, e.g., by boosting // Sema::IsOverload out to the AST library. - + // Function overloading is okay in C++. if (Importer.getToContext().getLangOpts().CPlusPlus) continue; - + // Complain about inconsistent function types. Importer.ToDiag(Loc, diag::err_odr_function_type_inconsistent) << Name << D->getType() << FoundFunction->getType(); @@ -3107,10 +1881,10 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { << FoundFunction->getType(); } } - + ConflictingDecls.push_back(FoundDecls[I]); } - + if (!ConflictingDecls.empty()) { Name = Importer.HandleNameConflict(Name, DC, IDNS, ConflictingDecls.data(), @@ -3259,6 +2033,9 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // Add this function to the lexical context. LexicalDC->addDeclInternal(ToFunction); + if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D)) + ImportOverrides(cast<CXXMethodDecl>(ToFunction), FromCXXMethod); + return ToFunction; } @@ -3315,12 +2092,12 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { if (!Name && getFieldIndex(D) != getFieldIndex(FoundField)) continue; - if (Importer.IsStructurallyEquivalent(D->getType(), + if (Importer.IsStructurallyEquivalent(D->getType(), FoundField->getType())) { Importer.Imported(D, FoundField); return FoundField; } - + Importer.ToDiag(Loc, diag::err_odr_field_type_inconsistent) << Name << D->getType() << FoundField->getType(); Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) @@ -3380,7 +2157,7 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { if (!Name && getFieldIndex(D) != getFieldIndex(FoundField)) continue; - if (Importer.IsStructurallyEquivalent(D->getType(), + if (Importer.IsStructurallyEquivalent(D->getType(), FoundField->getType(), !Name.isEmpty())) { Importer.Imported(D, FoundField); @@ -3504,12 +2281,12 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { if (ToD) return ToD; - // Determine whether we've already imported this ivar + // Determine whether we've already imported this ivar SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (ObjCIvarDecl *FoundIvar = dyn_cast<ObjCIvarDecl>(FoundDecls[I])) { - if (Importer.IsStructurallyEquivalent(D->getType(), + if (Importer.IsStructurallyEquivalent(D->getType(), FoundIvar->getType())) { Importer.Imported(D, FoundIvar); return FoundIvar; @@ -3568,12 +2345,12 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; - + if (VarDecl *FoundVar = dyn_cast<VarDecl>(FoundDecls[I])) { // We have found a variable that we may need to merge with. Check it. if (FoundVar->hasExternalFormalLinkage() && D->hasExternalFormalLinkage()) { - if (Importer.IsStructurallyEquivalent(D->getType(), + if (Importer.IsStructurallyEquivalent(D->getType(), FoundVar->getType())) { MergeWithVar = FoundVar; break; @@ -3671,6 +2448,9 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { if (ImportDefinition(D, ToVar)) return nullptr; + if (D->isConstexpr()) + ToVar->setConstexpr(true); + return ToVar; } @@ -3693,10 +2473,9 @@ Decl *ASTNodeImporter::VisitImplicitParamDecl(ImplicitParamDecl *D) { return nullptr; // Create the imported parameter. - ImplicitParamDecl *ToParm - = ImplicitParamDecl::Create(Importer.getToContext(), DC, - Loc, Name.getAsIdentifierInfo(), - T); + auto *ToParm = ImplicitParamDecl::Create(Importer.getToContext(), DC, Loc, + Name.getAsIdentifierInfo(), T, + D->getParameterKind()); return Importer.Imported(D, ToParm); } @@ -3724,8 +2503,27 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(), T, TInfo, D->getStorageClass(), - /*FIXME: Default argument*/nullptr); + /*DefaultArg*/ nullptr); + + // Set the default argument. ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg()); + ToParm->setKNRPromoted(D->isKNRPromoted()); + + Expr *ToDefArg = nullptr; + Expr *FromDefArg = nullptr; + if (D->hasUninstantiatedDefaultArg()) { + FromDefArg = D->getUninstantiatedDefaultArg(); + ToDefArg = Importer.Import(FromDefArg); + ToParm->setUninstantiatedDefaultArg(ToDefArg); + } else if (D->hasUnparsedDefaultArg()) { + ToParm->setUnparsedDefaultArg(); + } else if (D->hasDefaultArg()) { + FromDefArg = D->getDefaultArg(); + ToDefArg = Importer.Import(FromDefArg); + ToParm->setDefaultArg(ToDefArg); + } + if (FromDefArg && !ToDefArg) + return nullptr; if (D->isUsed()) ToParm->setIsUsed(); @@ -3775,12 +2573,12 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { } // Check parameter types. - for (ObjCMethodDecl::param_iterator P = D->param_begin(), + for (ObjCMethodDecl::param_iterator P = D->param_begin(), PEnd = D->param_end(), FoundP = FoundMethod->param_begin(); P != PEnd; ++P, ++FoundP) { - if (!Importer.IsStructurallyEquivalent((*P)->getType(), + if (!Importer.IsStructurallyEquivalent((*P)->getType(), (*FoundP)->getType())) { - Importer.FromDiag((*P)->getLocation(), + Importer.FromDiag((*P)->getLocation(), diag::err_odr_objc_method_param_type_inconsistent) << D->isInstanceMethod() << Name << (*P)->getType() << (*FoundP)->getType(); @@ -4386,7 +3184,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { if (ObjCPropertyDecl *FoundProp = dyn_cast<ObjCPropertyDecl>(FoundDecls[I])) { // Check property types. - if (!Importer.IsStructurallyEquivalent(D->getType(), + if (!Importer.IsStructurallyEquivalent(D->getType(), FoundProp->getType())) { Importer.ToDiag(Loc, diag::err_odr_objc_property_type_inconsistent) << Name << D->getType() << FoundProp->getType(); @@ -4424,8 +3222,10 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { ToProperty->setPropertyAttributes(D->getPropertyAttributes()); ToProperty->setPropertyAttributesAsWritten( D->getPropertyAttributesAsWritten()); - ToProperty->setGetterName(Importer.Import(D->getGetterName())); - ToProperty->setSetterName(Importer.Import(D->getSetterName())); + ToProperty->setGetterName(Importer.Import(D->getGetterName()), + Importer.Import(D->getGetterNameLoc())); + ToProperty->setSetterName(Importer.Import(D->getSetterName()), + Importer.Import(D->getSetterNameLoc())); ToProperty->setGetterMethodDecl( cast_or_null<ObjCMethodDecl>(Importer.Import(D->getGetterMethodDecl()))); ToProperty->setSetterMethodDecl( @@ -4753,12 +3553,46 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( } } else { // Create a new specialization. - D2 = ClassTemplateSpecializationDecl::Create(Importer.getToContext(), - D->getTagKind(), DC, - StartLoc, IdLoc, - ClassTemplate, - TemplateArgs, - /*PrevDecl=*/nullptr); + if (ClassTemplatePartialSpecializationDecl *PartialSpec = + dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) { + + // Import TemplateArgumentListInfo + TemplateArgumentListInfo ToTAInfo; + auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten(); + for (unsigned I = 0, E = ASTTemplateArgs.NumTemplateArgs; I < E; ++I) { + bool Error = false; + auto ToLoc = ImportTemplateArgumentLoc(ASTTemplateArgs[I], Error); + if (Error) + return nullptr; + ToTAInfo.addArgument(ToLoc); + } + + QualType CanonInjType = Importer.Import( + PartialSpec->getInjectedSpecializationType()); + if (CanonInjType.isNull()) + return nullptr; + CanonInjType = CanonInjType.getCanonicalType(); + + TemplateParameterList *ToTPList = ImportTemplateParameterList( + PartialSpec->getTemplateParameters()); + if (!ToTPList && PartialSpec->getTemplateParameters()) + return nullptr; + + D2 = ClassTemplatePartialSpecializationDecl::Create( + Importer.getToContext(), D->getTagKind(), DC, StartLoc, IdLoc, + ToTPList, ClassTemplate, + llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()), + ToTAInfo, CanonInjType, nullptr); + + } else { + D2 = ClassTemplateSpecializationDecl::Create(Importer.getToContext(), + D->getTagKind(), DC, + StartLoc, IdLoc, + ClassTemplate, + TemplateArgs, + /*PrevDecl=*/nullptr); + } + D2->setSpecializationKind(D->getSpecializationKind()); // Add this specialization to the class template. @@ -4766,13 +3600,31 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( // Import the qualifier, if any. D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); - + + Importer.Imported(D, D2); + + if (auto *TSI = D->getTypeAsWritten()) { + TypeSourceInfo *TInfo = Importer.Import(TSI); + if (!TInfo) + return nullptr; + D2->setTypeAsWritten(TInfo); + D2->setTemplateKeywordLoc(Importer.Import(D->getTemplateKeywordLoc())); + D2->setExternLoc(Importer.Import(D->getExternLoc())); + } + + SourceLocation POI = Importer.Import(D->getPointOfInstantiation()); + if (POI.isValid()) + D2->setPointOfInstantiation(POI); + else if (D->getPointOfInstantiation().isValid()) + return nullptr; + + D2->setTemplateSpecializationKind(D->getTemplateSpecializationKind()); + // Add the specialization to this context. D2->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(D2); } Importer.Imported(D, D2); - if (D->isCompleteDefinition() && ImportDefinition(D, D2)) return nullptr; @@ -5010,13 +3862,17 @@ Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { SmallVector<IdentifierInfo *, 4> Names; for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) { IdentifierInfo *ToII = Importer.Import(S->getOutputIdentifier(I)); - if (!ToII) + // ToII is nullptr when no symbolic name is given for output operand + // see ParseStmtAsm::ParseAsmOperandsOpt + if (!ToII && S->getOutputIdentifier(I)) return nullptr; Names.push_back(ToII); } for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) { IdentifierInfo *ToII = Importer.Import(S->getInputIdentifier(I)); - if (!ToII) + // ToII is nullptr when no symbolic name is given for input operand + // see ParseStmtAsm::ParseAsmOperandsOpt + if (!ToII && S->getInputIdentifier(I)) return nullptr; Names.push_back(ToII); } @@ -5860,7 +4716,7 @@ Expr *ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) { T, E->getValueKind(), E->getObjectKind(), Importer.Import(E->getOperatorLoc()), - E->isFPContractable()); + E->getFPFeatures()); } Expr *ASTNodeImporter::VisitConditionalOperator(ConditionalOperator *E) { @@ -6010,7 +4866,7 @@ Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { E->getObjectKind(), CompLHSType, CompResultType, Importer.Import(E->getOperatorLoc()), - E->isFPContractable()); + E->getFPFeatures()); } bool ASTNodeImporter::ImportCastPath(CastExpr *CE, CXXCastPath &Path) { @@ -6633,6 +5489,35 @@ Expr *ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { } } + +Expr *ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr( + SubstNonTypeTemplateParmExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + NonTypeTemplateParmDecl *Param = cast_or_null<NonTypeTemplateParmDecl>( + Importer.Import(E->getParameter())); + if (!Param) + return nullptr; + + Expr *Replacement = Importer.Import(E->getReplacement()); + if (!Replacement) + return nullptr; + + return new (Importer.getToContext()) SubstNonTypeTemplateParmExpr( + T, E->getValueKind(), Importer.Import(E->getExprLoc()), Param, + Replacement); +} + +void ASTNodeImporter::ImportOverrides(CXXMethodDecl *ToMethod, + CXXMethodDecl *FromMethod) { + for (auto *FromOverriddenMethod : FromMethod->overridden_methods()) + ToMethod->addOverriddenMethod( + cast<CXXMethodDecl>(Importer.Import(const_cast<CXXMethodDecl*>( + FromOverriddenMethod)))); +} + ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, ASTContext &FromContext, FileManager &FromFileManager, bool MinimalImport) @@ -6839,14 +5724,14 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { case NestedNameSpecifier::Namespace: if (NamespaceDecl *NS = - cast<NamespaceDecl>(Import(FromNNS->getAsNamespace()))) { + cast_or_null<NamespaceDecl>(Import(FromNNS->getAsNamespace()))) { return NestedNameSpecifier::Create(ToContext, prefix, NS); } return nullptr; case NestedNameSpecifier::NamespaceAlias: if (NamespaceAliasDecl *NSAD = - cast<NamespaceAliasDecl>(Import(FromNNS->getAsNamespaceAlias()))) { + cast_or_null<NamespaceAliasDecl>(Import(FromNNS->getAsNamespaceAlias()))) { return NestedNameSpecifier::Create(ToContext, prefix, NSAD); } return nullptr; @@ -6856,7 +5741,7 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { case NestedNameSpecifier::Super: if (CXXRecordDecl *RD = - cast<CXXRecordDecl>(Import(FromNNS->getAsRecordDecl()))) { + cast_or_null<CXXRecordDecl>(Import(FromNNS->getAsRecordDecl()))) { return NestedNameSpecifier::SuperSpecifier(ToContext, RD); } return nullptr; @@ -6878,8 +5763,74 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { } NestedNameSpecifierLoc ASTImporter::Import(NestedNameSpecifierLoc FromNNS) { - // FIXME: Implement! - return NestedNameSpecifierLoc(); + // Copied from NestedNameSpecifier mostly. + SmallVector<NestedNameSpecifierLoc , 8> NestedNames; + NestedNameSpecifierLoc NNS = FromNNS; + + // Push each of the nested-name-specifiers's onto a stack for + // serialization in reverse order. + while (NNS) { + NestedNames.push_back(NNS); + NNS = NNS.getPrefix(); + } + + NestedNameSpecifierLocBuilder Builder; + + while (!NestedNames.empty()) { + NNS = NestedNames.pop_back_val(); + NestedNameSpecifier *Spec = Import(NNS.getNestedNameSpecifier()); + if (!Spec) + return NestedNameSpecifierLoc(); + + NestedNameSpecifier::SpecifierKind Kind = Spec->getKind(); + switch (Kind) { + case NestedNameSpecifier::Identifier: + Builder.Extend(getToContext(), + Spec->getAsIdentifier(), + Import(NNS.getLocalBeginLoc()), + Import(NNS.getLocalEndLoc())); + break; + + case NestedNameSpecifier::Namespace: + Builder.Extend(getToContext(), + Spec->getAsNamespace(), + Import(NNS.getLocalBeginLoc()), + Import(NNS.getLocalEndLoc())); + break; + + case NestedNameSpecifier::NamespaceAlias: + Builder.Extend(getToContext(), + Spec->getAsNamespaceAlias(), + Import(NNS.getLocalBeginLoc()), + Import(NNS.getLocalEndLoc())); + break; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: { + TypeSourceInfo *TSI = getToContext().getTrivialTypeSourceInfo( + QualType(Spec->getAsType(), 0)); + Builder.Extend(getToContext(), + Import(NNS.getLocalBeginLoc()), + TSI->getTypeLoc(), + Import(NNS.getLocalEndLoc())); + break; + } + + case NestedNameSpecifier::Global: + Builder.MakeGlobal(getToContext(), Import(NNS.getLocalBeginLoc())); + break; + + case NestedNameSpecifier::Super: { + SourceRange ToRange = Import(NNS.getSourceRange()); + Builder.MakeSuper(getToContext(), + Spec->getAsRecordDecl(), + ToRange.getBegin(), + ToRange.getEnd()); + } + } + } + + return Builder.getWithLocInContext(getToContext()); } TemplateName ASTImporter::Import(TemplateName From) { @@ -7175,6 +6126,14 @@ DeclarationName ASTImporter::Import(DeclarationName FromName) { ToContext.getCanonicalType(T)); } + case DeclarationName::CXXDeductionGuideName: { + TemplateDecl *Template = cast_or_null<TemplateDecl>( + Import(FromName.getCXXDeductionGuideTemplate())); + if (!Template) + return DeclarationName(); + return ToContext.DeclarationNames.getCXXDeductionGuideName(Template); + } + case DeclarationName::CXXConversionFunctionName: { QualType T = Import(FromName.getCXXNameType()); if (T.isNull()) @@ -7288,7 +6247,7 @@ bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To, = ImportedTypes.find(From.getTypePtr()); if (Pos != ImportedTypes.end() && ToContext.hasSameType(Import(From), To)) return true; - + StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls, false, Complain); return Ctx.IsStructurallyEquivalent(From, To); diff --git a/contrib/llvm/tools/clang/lib/AST/ASTStructuralEquivalence.cpp b/contrib/llvm/tools/clang/lib/AST/ASTStructuralEquivalence.cpp new file mode 100644 index 0000000..ea7faab --- /dev/null +++ b/contrib/llvm/tools/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -0,0 +1,1362 @@ +//===--- ASTStructuralEquivalence.cpp - -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implement StructuralEquivalenceContext class and helper functions +// for layout matching. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ASTStructuralEquivalence.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTDiagnostic.h" +#include "clang/AST/ASTImporter.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclVisitor.h" +#include "clang/AST/StmtVisitor.h" +#include "clang/AST/TypeVisitor.h" +#include "clang/Basic/SourceManager.h" + +namespace { + +using namespace clang; + +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + QualType T1, QualType T2); +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + Decl *D1, Decl *D2); +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + const TemplateArgument &Arg1, + const TemplateArgument &Arg2); + +/// Determine structural equivalence of two expressions. +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + Expr *E1, Expr *E2) { + if (!E1 || !E2) + return E1 == E2; + + // FIXME: Actually perform a structural comparison! + return true; +} + +/// Determine whether two identifiers are equivalent. +static bool IsStructurallyEquivalent(const IdentifierInfo *Name1, + const IdentifierInfo *Name2) { + if (!Name1 || !Name2) + return Name1 == Name2; + + return Name1->getName() == Name2->getName(); +} + +/// Determine whether two nested-name-specifiers are equivalent. +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + NestedNameSpecifier *NNS1, + NestedNameSpecifier *NNS2) { + if (NNS1->getKind() != NNS2->getKind()) + return false; + + NestedNameSpecifier *Prefix1 = NNS1->getPrefix(), + *Prefix2 = NNS2->getPrefix(); + if ((bool)Prefix1 != (bool)Prefix2) + return false; + + if (Prefix1) + if (!IsStructurallyEquivalent(Context, Prefix1, Prefix2)) + return false; + + switch (NNS1->getKind()) { + case NestedNameSpecifier::Identifier: + return IsStructurallyEquivalent(NNS1->getAsIdentifier(), + NNS2->getAsIdentifier()); + case NestedNameSpecifier::Namespace: + return IsStructurallyEquivalent(Context, NNS1->getAsNamespace(), + NNS2->getAsNamespace()); + case NestedNameSpecifier::NamespaceAlias: + return IsStructurallyEquivalent(Context, NNS1->getAsNamespaceAlias(), + NNS2->getAsNamespaceAlias()); + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + return IsStructurallyEquivalent(Context, QualType(NNS1->getAsType(), 0), + QualType(NNS2->getAsType(), 0)); + case NestedNameSpecifier::Global: + return true; + case NestedNameSpecifier::Super: + return IsStructurallyEquivalent(Context, NNS1->getAsRecordDecl(), + NNS2->getAsRecordDecl()); + } + return false; +} + +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + const TemplateName &N1, + const TemplateName &N2) { + if (N1.getKind() != N2.getKind()) + return false; + switch (N1.getKind()) { + case TemplateName::Template: + return IsStructurallyEquivalent(Context, N1.getAsTemplateDecl(), + N2.getAsTemplateDecl()); + + case TemplateName::OverloadedTemplate: { + OverloadedTemplateStorage *OS1 = N1.getAsOverloadedTemplate(), + *OS2 = N2.getAsOverloadedTemplate(); + OverloadedTemplateStorage::iterator I1 = OS1->begin(), I2 = OS2->begin(), + E1 = OS1->end(), E2 = OS2->end(); + for (; I1 != E1 && I2 != E2; ++I1, ++I2) + if (!IsStructurallyEquivalent(Context, *I1, *I2)) + return false; + return I1 == E1 && I2 == E2; + } + + case TemplateName::QualifiedTemplate: { + QualifiedTemplateName *QN1 = N1.getAsQualifiedTemplateName(), + *QN2 = N2.getAsQualifiedTemplateName(); + return IsStructurallyEquivalent(Context, QN1->getDecl(), QN2->getDecl()) && + IsStructurallyEquivalent(Context, QN1->getQualifier(), + QN2->getQualifier()); + } + + case TemplateName::DependentTemplate: { + DependentTemplateName *DN1 = N1.getAsDependentTemplateName(), + *DN2 = N2.getAsDependentTemplateName(); + if (!IsStructurallyEquivalent(Context, DN1->getQualifier(), + DN2->getQualifier())) + return false; + if (DN1->isIdentifier() && DN2->isIdentifier()) + return IsStructurallyEquivalent(DN1->getIdentifier(), + DN2->getIdentifier()); + else if (DN1->isOverloadedOperator() && DN2->isOverloadedOperator()) + return DN1->getOperator() == DN2->getOperator(); + return false; + } + + case TemplateName::SubstTemplateTemplateParm: { + SubstTemplateTemplateParmStorage *TS1 = N1.getAsSubstTemplateTemplateParm(), + *TS2 = N2.getAsSubstTemplateTemplateParm(); + return IsStructurallyEquivalent(Context, TS1->getParameter(), + TS2->getParameter()) && + IsStructurallyEquivalent(Context, TS1->getReplacement(), + TS2->getReplacement()); + } + case TemplateName::SubstTemplateTemplateParmPack: { + SubstTemplateTemplateParmPackStorage + *P1 = N1.getAsSubstTemplateTemplateParmPack(), + *P2 = N2.getAsSubstTemplateTemplateParmPack(); + return IsStructurallyEquivalent(Context, P1->getArgumentPack(), + P2->getArgumentPack()) && + IsStructurallyEquivalent(Context, P1->getParameterPack(), + P2->getParameterPack()); + } + } + return false; +} + +/// Determine whether two template arguments are equivalent. +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + const TemplateArgument &Arg1, + const TemplateArgument &Arg2) { + if (Arg1.getKind() != Arg2.getKind()) + return false; + + switch (Arg1.getKind()) { + case TemplateArgument::Null: + return true; + + case TemplateArgument::Type: + return Context.IsStructurallyEquivalent(Arg1.getAsType(), Arg2.getAsType()); + + case TemplateArgument::Integral: + if (!Context.IsStructurallyEquivalent(Arg1.getIntegralType(), + Arg2.getIntegralType())) + return false; + + return llvm::APSInt::isSameValue(Arg1.getAsIntegral(), + Arg2.getAsIntegral()); + + case TemplateArgument::Declaration: + return Context.IsStructurallyEquivalent(Arg1.getAsDecl(), Arg2.getAsDecl()); + + case TemplateArgument::NullPtr: + return true; // FIXME: Is this correct? + + case TemplateArgument::Template: + return IsStructurallyEquivalent(Context, Arg1.getAsTemplate(), + Arg2.getAsTemplate()); + + case TemplateArgument::TemplateExpansion: + return IsStructurallyEquivalent(Context, + Arg1.getAsTemplateOrTemplatePattern(), + Arg2.getAsTemplateOrTemplatePattern()); + + case TemplateArgument::Expression: + return IsStructurallyEquivalent(Context, Arg1.getAsExpr(), + Arg2.getAsExpr()); + + case TemplateArgument::Pack: + if (Arg1.pack_size() != Arg2.pack_size()) + return false; + + for (unsigned I = 0, N = Arg1.pack_size(); I != N; ++I) + if (!IsStructurallyEquivalent(Context, Arg1.pack_begin()[I], + Arg2.pack_begin()[I])) + return false; + + return true; + } + + llvm_unreachable("Invalid template argument kind"); +} + +/// Determine structural equivalence for the common part of array +/// types. +static bool IsArrayStructurallyEquivalent(StructuralEquivalenceContext &Context, + const ArrayType *Array1, + const ArrayType *Array2) { + if (!IsStructurallyEquivalent(Context, Array1->getElementType(), + Array2->getElementType())) + return false; + if (Array1->getSizeModifier() != Array2->getSizeModifier()) + return false; + if (Array1->getIndexTypeQualifiers() != Array2->getIndexTypeQualifiers()) + return false; + + return true; +} + +/// Determine structural equivalence of two types. +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + QualType T1, QualType T2) { + if (T1.isNull() || T2.isNull()) + return T1.isNull() && T2.isNull(); + + if (!Context.StrictTypeSpelling) { + // We aren't being strict about token-to-token equivalence of types, + // so map down to the canonical type. + T1 = Context.FromCtx.getCanonicalType(T1); + T2 = Context.ToCtx.getCanonicalType(T2); + } + + if (T1.getQualifiers() != T2.getQualifiers()) + return false; + + Type::TypeClass TC = T1->getTypeClass(); + + if (T1->getTypeClass() != T2->getTypeClass()) { + // Compare function types with prototypes vs. without prototypes as if + // both did not have prototypes. + if (T1->getTypeClass() == Type::FunctionProto && + T2->getTypeClass() == Type::FunctionNoProto) + TC = Type::FunctionNoProto; + else if (T1->getTypeClass() == Type::FunctionNoProto && + T2->getTypeClass() == Type::FunctionProto) + TC = Type::FunctionNoProto; + else + return false; + } + + switch (TC) { + case Type::Builtin: + // FIXME: Deal with Char_S/Char_U. + if (cast<BuiltinType>(T1)->getKind() != cast<BuiltinType>(T2)->getKind()) + return false; + break; + + case Type::Complex: + if (!IsStructurallyEquivalent(Context, + cast<ComplexType>(T1)->getElementType(), + cast<ComplexType>(T2)->getElementType())) + return false; + break; + + case Type::Adjusted: + case Type::Decayed: + if (!IsStructurallyEquivalent(Context, + cast<AdjustedType>(T1)->getOriginalType(), + cast<AdjustedType>(T2)->getOriginalType())) + return false; + break; + + case Type::Pointer: + if (!IsStructurallyEquivalent(Context, + cast<PointerType>(T1)->getPointeeType(), + cast<PointerType>(T2)->getPointeeType())) + return false; + break; + + case Type::BlockPointer: + if (!IsStructurallyEquivalent(Context, + cast<BlockPointerType>(T1)->getPointeeType(), + cast<BlockPointerType>(T2)->getPointeeType())) + return false; + break; + + case Type::LValueReference: + case Type::RValueReference: { + const ReferenceType *Ref1 = cast<ReferenceType>(T1); + const ReferenceType *Ref2 = cast<ReferenceType>(T2); + if (Ref1->isSpelledAsLValue() != Ref2->isSpelledAsLValue()) + return false; + if (Ref1->isInnerRef() != Ref2->isInnerRef()) + return false; + if (!IsStructurallyEquivalent(Context, Ref1->getPointeeTypeAsWritten(), + Ref2->getPointeeTypeAsWritten())) + return false; + break; + } + + case Type::MemberPointer: { + const MemberPointerType *MemPtr1 = cast<MemberPointerType>(T1); + const MemberPointerType *MemPtr2 = cast<MemberPointerType>(T2); + if (!IsStructurallyEquivalent(Context, MemPtr1->getPointeeType(), + MemPtr2->getPointeeType())) + return false; + if (!IsStructurallyEquivalent(Context, QualType(MemPtr1->getClass(), 0), + QualType(MemPtr2->getClass(), 0))) + return false; + break; + } + + case Type::ConstantArray: { + const ConstantArrayType *Array1 = cast<ConstantArrayType>(T1); + const ConstantArrayType *Array2 = cast<ConstantArrayType>(T2); + if (!llvm::APInt::isSameValue(Array1->getSize(), Array2->getSize())) + return false; + + if (!IsArrayStructurallyEquivalent(Context, Array1, Array2)) + return false; + break; + } + + case Type::IncompleteArray: + if (!IsArrayStructurallyEquivalent(Context, cast<ArrayType>(T1), + cast<ArrayType>(T2))) + return false; + break; + + case Type::VariableArray: { + const VariableArrayType *Array1 = cast<VariableArrayType>(T1); + const VariableArrayType *Array2 = cast<VariableArrayType>(T2); + if (!IsStructurallyEquivalent(Context, Array1->getSizeExpr(), + Array2->getSizeExpr())) + return false; + + if (!IsArrayStructurallyEquivalent(Context, Array1, Array2)) + return false; + + break; + } + + case Type::DependentSizedArray: { + const DependentSizedArrayType *Array1 = cast<DependentSizedArrayType>(T1); + const DependentSizedArrayType *Array2 = cast<DependentSizedArrayType>(T2); + if (!IsStructurallyEquivalent(Context, Array1->getSizeExpr(), + Array2->getSizeExpr())) + return false; + + if (!IsArrayStructurallyEquivalent(Context, Array1, Array2)) + return false; + + break; + } + + case Type::DependentSizedExtVector: { + const DependentSizedExtVectorType *Vec1 = + cast<DependentSizedExtVectorType>(T1); + const DependentSizedExtVectorType *Vec2 = + cast<DependentSizedExtVectorType>(T2); + if (!IsStructurallyEquivalent(Context, Vec1->getSizeExpr(), + Vec2->getSizeExpr())) + return false; + if (!IsStructurallyEquivalent(Context, Vec1->getElementType(), + Vec2->getElementType())) + return false; + break; + } + + case Type::Vector: + case Type::ExtVector: { + const VectorType *Vec1 = cast<VectorType>(T1); + const VectorType *Vec2 = cast<VectorType>(T2); + if (!IsStructurallyEquivalent(Context, Vec1->getElementType(), + Vec2->getElementType())) + return false; + if (Vec1->getNumElements() != Vec2->getNumElements()) + return false; + if (Vec1->getVectorKind() != Vec2->getVectorKind()) + return false; + break; + } + + case Type::FunctionProto: { + const FunctionProtoType *Proto1 = cast<FunctionProtoType>(T1); + const FunctionProtoType *Proto2 = cast<FunctionProtoType>(T2); + if (Proto1->getNumParams() != Proto2->getNumParams()) + return false; + for (unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) { + if (!IsStructurallyEquivalent(Context, Proto1->getParamType(I), + Proto2->getParamType(I))) + return false; + } + if (Proto1->isVariadic() != Proto2->isVariadic()) + return false; + if (Proto1->getExceptionSpecType() != Proto2->getExceptionSpecType()) + return false; + if (Proto1->getExceptionSpecType() == EST_Dynamic) { + if (Proto1->getNumExceptions() != Proto2->getNumExceptions()) + return false; + for (unsigned I = 0, N = Proto1->getNumExceptions(); I != N; ++I) { + if (!IsStructurallyEquivalent(Context, Proto1->getExceptionType(I), + Proto2->getExceptionType(I))) + return false; + } + } else if (Proto1->getExceptionSpecType() == EST_ComputedNoexcept) { + if (!IsStructurallyEquivalent(Context, Proto1->getNoexceptExpr(), + Proto2->getNoexceptExpr())) + return false; + } + if (Proto1->getTypeQuals() != Proto2->getTypeQuals()) + return false; + + // Fall through to check the bits common with FunctionNoProtoType. + LLVM_FALLTHROUGH; + } + + case Type::FunctionNoProto: { + const FunctionType *Function1 = cast<FunctionType>(T1); + const FunctionType *Function2 = cast<FunctionType>(T2); + if (!IsStructurallyEquivalent(Context, Function1->getReturnType(), + Function2->getReturnType())) + return false; + if (Function1->getExtInfo() != Function2->getExtInfo()) + return false; + break; + } + + case Type::UnresolvedUsing: + if (!IsStructurallyEquivalent(Context, + cast<UnresolvedUsingType>(T1)->getDecl(), + cast<UnresolvedUsingType>(T2)->getDecl())) + return false; + + break; + + case Type::Attributed: + if (!IsStructurallyEquivalent(Context, + cast<AttributedType>(T1)->getModifiedType(), + cast<AttributedType>(T2)->getModifiedType())) + return false; + if (!IsStructurallyEquivalent( + Context, cast<AttributedType>(T1)->getEquivalentType(), + cast<AttributedType>(T2)->getEquivalentType())) + return false; + break; + + case Type::Paren: + if (!IsStructurallyEquivalent(Context, cast<ParenType>(T1)->getInnerType(), + cast<ParenType>(T2)->getInnerType())) + return false; + break; + + case Type::Typedef: + if (!IsStructurallyEquivalent(Context, cast<TypedefType>(T1)->getDecl(), + cast<TypedefType>(T2)->getDecl())) + return false; + break; + + case Type::TypeOfExpr: + if (!IsStructurallyEquivalent( + Context, cast<TypeOfExprType>(T1)->getUnderlyingExpr(), + cast<TypeOfExprType>(T2)->getUnderlyingExpr())) + return false; + break; + + case Type::TypeOf: + if (!IsStructurallyEquivalent(Context, + cast<TypeOfType>(T1)->getUnderlyingType(), + cast<TypeOfType>(T2)->getUnderlyingType())) + return false; + break; + + case Type::UnaryTransform: + if (!IsStructurallyEquivalent( + Context, cast<UnaryTransformType>(T1)->getUnderlyingType(), + cast<UnaryTransformType>(T1)->getUnderlyingType())) + return false; + break; + + case Type::Decltype: + if (!IsStructurallyEquivalent(Context, + cast<DecltypeType>(T1)->getUnderlyingExpr(), + cast<DecltypeType>(T2)->getUnderlyingExpr())) + return false; + break; + + case Type::Auto: + if (!IsStructurallyEquivalent(Context, cast<AutoType>(T1)->getDeducedType(), + cast<AutoType>(T2)->getDeducedType())) + return false; + break; + + case Type::DeducedTemplateSpecialization: { + auto *DT1 = cast<DeducedTemplateSpecializationType>(T1); + auto *DT2 = cast<DeducedTemplateSpecializationType>(T2); + if (!IsStructurallyEquivalent(Context, DT1->getTemplateName(), + DT2->getTemplateName())) + return false; + if (!IsStructurallyEquivalent(Context, DT1->getDeducedType(), + DT2->getDeducedType())) + return false; + break; + } + + case Type::Record: + case Type::Enum: + if (!IsStructurallyEquivalent(Context, cast<TagType>(T1)->getDecl(), + cast<TagType>(T2)->getDecl())) + return false; + break; + + case Type::TemplateTypeParm: { + const TemplateTypeParmType *Parm1 = cast<TemplateTypeParmType>(T1); + const TemplateTypeParmType *Parm2 = cast<TemplateTypeParmType>(T2); + if (Parm1->getDepth() != Parm2->getDepth()) + return false; + if (Parm1->getIndex() != Parm2->getIndex()) + return false; + if (Parm1->isParameterPack() != Parm2->isParameterPack()) + return false; + + // Names of template type parameters are never significant. + break; + } + + case Type::SubstTemplateTypeParm: { + const SubstTemplateTypeParmType *Subst1 = + cast<SubstTemplateTypeParmType>(T1); + const SubstTemplateTypeParmType *Subst2 = + cast<SubstTemplateTypeParmType>(T2); + if (!IsStructurallyEquivalent(Context, + QualType(Subst1->getReplacedParameter(), 0), + QualType(Subst2->getReplacedParameter(), 0))) + return false; + if (!IsStructurallyEquivalent(Context, Subst1->getReplacementType(), + Subst2->getReplacementType())) + return false; + break; + } + + case Type::SubstTemplateTypeParmPack: { + const SubstTemplateTypeParmPackType *Subst1 = + cast<SubstTemplateTypeParmPackType>(T1); + const SubstTemplateTypeParmPackType *Subst2 = + cast<SubstTemplateTypeParmPackType>(T2); + if (!IsStructurallyEquivalent(Context, + QualType(Subst1->getReplacedParameter(), 0), + QualType(Subst2->getReplacedParameter(), 0))) + return false; + if (!IsStructurallyEquivalent(Context, Subst1->getArgumentPack(), + Subst2->getArgumentPack())) + return false; + break; + } + case Type::TemplateSpecialization: { + const TemplateSpecializationType *Spec1 = + cast<TemplateSpecializationType>(T1); + const TemplateSpecializationType *Spec2 = + cast<TemplateSpecializationType>(T2); + if (!IsStructurallyEquivalent(Context, Spec1->getTemplateName(), + Spec2->getTemplateName())) + return false; + if (Spec1->getNumArgs() != Spec2->getNumArgs()) + return false; + for (unsigned I = 0, N = Spec1->getNumArgs(); I != N; ++I) { + if (!IsStructurallyEquivalent(Context, Spec1->getArg(I), + Spec2->getArg(I))) + return false; + } + break; + } + + case Type::Elaborated: { + const ElaboratedType *Elab1 = cast<ElaboratedType>(T1); + const ElaboratedType *Elab2 = cast<ElaboratedType>(T2); + // CHECKME: what if a keyword is ETK_None or ETK_typename ? + if (Elab1->getKeyword() != Elab2->getKeyword()) + return false; + if (!IsStructurallyEquivalent(Context, Elab1->getQualifier(), + Elab2->getQualifier())) + return false; + if (!IsStructurallyEquivalent(Context, Elab1->getNamedType(), + Elab2->getNamedType())) + return false; + break; + } + + case Type::InjectedClassName: { + const InjectedClassNameType *Inj1 = cast<InjectedClassNameType>(T1); + const InjectedClassNameType *Inj2 = cast<InjectedClassNameType>(T2); + if (!IsStructurallyEquivalent(Context, + Inj1->getInjectedSpecializationType(), + Inj2->getInjectedSpecializationType())) + return false; + break; + } + + case Type::DependentName: { + const DependentNameType *Typename1 = cast<DependentNameType>(T1); + const DependentNameType *Typename2 = cast<DependentNameType>(T2); + if (!IsStructurallyEquivalent(Context, Typename1->getQualifier(), + Typename2->getQualifier())) + return false; + if (!IsStructurallyEquivalent(Typename1->getIdentifier(), + Typename2->getIdentifier())) + return false; + + break; + } + + case Type::DependentTemplateSpecialization: { + const DependentTemplateSpecializationType *Spec1 = + cast<DependentTemplateSpecializationType>(T1); + const DependentTemplateSpecializationType *Spec2 = + cast<DependentTemplateSpecializationType>(T2); + if (!IsStructurallyEquivalent(Context, Spec1->getQualifier(), + Spec2->getQualifier())) + return false; + if (!IsStructurallyEquivalent(Spec1->getIdentifier(), + Spec2->getIdentifier())) + return false; + if (Spec1->getNumArgs() != Spec2->getNumArgs()) + return false; + for (unsigned I = 0, N = Spec1->getNumArgs(); I != N; ++I) { + if (!IsStructurallyEquivalent(Context, Spec1->getArg(I), + Spec2->getArg(I))) + return false; + } + break; + } + + case Type::PackExpansion: + if (!IsStructurallyEquivalent(Context, + cast<PackExpansionType>(T1)->getPattern(), + cast<PackExpansionType>(T2)->getPattern())) + return false; + break; + + case Type::ObjCInterface: { + const ObjCInterfaceType *Iface1 = cast<ObjCInterfaceType>(T1); + const ObjCInterfaceType *Iface2 = cast<ObjCInterfaceType>(T2); + if (!IsStructurallyEquivalent(Context, Iface1->getDecl(), + Iface2->getDecl())) + return false; + 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); + if (!IsStructurallyEquivalent(Context, Obj1->getBaseType(), + Obj2->getBaseType())) + 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::ObjCObjectPointer: { + const ObjCObjectPointerType *Ptr1 = cast<ObjCObjectPointerType>(T1); + const ObjCObjectPointerType *Ptr2 = cast<ObjCObjectPointerType>(T2); + if (!IsStructurallyEquivalent(Context, Ptr1->getPointeeType(), + Ptr2->getPointeeType())) + return false; + break; + } + + case Type::Atomic: { + if (!IsStructurallyEquivalent(Context, cast<AtomicType>(T1)->getValueType(), + cast<AtomicType>(T2)->getValueType())) + return false; + break; + } + + case Type::Pipe: { + if (!IsStructurallyEquivalent(Context, cast<PipeType>(T1)->getElementType(), + cast<PipeType>(T2)->getElementType())) + return false; + break; + } + + } // end switch + + return true; +} + +/// Determine structural equivalence of two fields. +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + FieldDecl *Field1, FieldDecl *Field2) { + RecordDecl *Owner2 = cast<RecordDecl>(Field2->getDeclContext()); + + // For anonymous structs/unions, match up the anonymous struct/union type + // declarations directly, so that we don't go off searching for anonymous + // types + if (Field1->isAnonymousStructOrUnion() && + Field2->isAnonymousStructOrUnion()) { + RecordDecl *D1 = Field1->getType()->castAs<RecordType>()->getDecl(); + RecordDecl *D2 = Field2->getType()->castAs<RecordType>()->getDecl(); + return IsStructurallyEquivalent(Context, D1, D2); + } + + // Check for equivalent field names. + IdentifierInfo *Name1 = Field1->getIdentifier(); + IdentifierInfo *Name2 = Field2->getIdentifier(); + if (!::IsStructurallyEquivalent(Name1, Name2)) { + if (Context.Complain) { + Context.Diag2(Owner2->getLocation(), + Context.ErrorOnTagTypeMismatch + ? diag::err_odr_tag_type_inconsistent + : diag::warn_odr_tag_type_inconsistent) + << Context.ToCtx.getTypeDeclType(Owner2); + Context.Diag2(Field2->getLocation(), diag::note_odr_field_name) + << Field2->getDeclName(); + Context.Diag1(Field1->getLocation(), diag::note_odr_field_name) + << Field1->getDeclName(); + } + return false; + } + + if (!IsStructurallyEquivalent(Context, Field1->getType(), + Field2->getType())) { + if (Context.Complain) { + Context.Diag2(Owner2->getLocation(), + Context.ErrorOnTagTypeMismatch + ? diag::err_odr_tag_type_inconsistent + : diag::warn_odr_tag_type_inconsistent) + << Context.ToCtx.getTypeDeclType(Owner2); + Context.Diag2(Field2->getLocation(), diag::note_odr_field) + << Field2->getDeclName() << Field2->getType(); + Context.Diag1(Field1->getLocation(), diag::note_odr_field) + << Field1->getDeclName() << Field1->getType(); + } + return false; + } + + if (Field1->isBitField() != Field2->isBitField()) { + if (Context.Complain) { + Context.Diag2(Owner2->getLocation(), + Context.ErrorOnTagTypeMismatch + ? diag::err_odr_tag_type_inconsistent + : diag::warn_odr_tag_type_inconsistent) + << Context.ToCtx.getTypeDeclType(Owner2); + if (Field1->isBitField()) { + Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field) + << Field1->getDeclName() << Field1->getType() + << Field1->getBitWidthValue(Context.FromCtx); + Context.Diag2(Field2->getLocation(), diag::note_odr_not_bit_field) + << Field2->getDeclName(); + } else { + Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field) + << Field2->getDeclName() << Field2->getType() + << Field2->getBitWidthValue(Context.ToCtx); + Context.Diag1(Field1->getLocation(), diag::note_odr_not_bit_field) + << Field1->getDeclName(); + } + } + return false; + } + + if (Field1->isBitField()) { + // Make sure that the bit-fields are the same length. + unsigned Bits1 = Field1->getBitWidthValue(Context.FromCtx); + unsigned Bits2 = Field2->getBitWidthValue(Context.ToCtx); + + if (Bits1 != Bits2) { + if (Context.Complain) { + Context.Diag2(Owner2->getLocation(), + Context.ErrorOnTagTypeMismatch + ? diag::err_odr_tag_type_inconsistent + : diag::warn_odr_tag_type_inconsistent) + << Context.ToCtx.getTypeDeclType(Owner2); + Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field) + << Field2->getDeclName() << Field2->getType() << Bits2; + Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field) + << Field1->getDeclName() << Field1->getType() << Bits1; + } + return false; + } + } + + return true; +} + +/// Determine structural equivalence of two records. +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + RecordDecl *D1, RecordDecl *D2) { + if (D1->isUnion() != D2->isUnion()) { + if (Context.Complain) { + Context.Diag2(D2->getLocation(), + Context.ErrorOnTagTypeMismatch + ? diag::err_odr_tag_type_inconsistent + : diag::warn_odr_tag_type_inconsistent) + << Context.ToCtx.getTypeDeclType(D2); + Context.Diag1(D1->getLocation(), diag::note_odr_tag_kind_here) + << D1->getDeclName() << (unsigned)D1->getTagKind(); + } + return false; + } + + if (D1->isAnonymousStructOrUnion() && D2->isAnonymousStructOrUnion()) { + // If both anonymous structs/unions are in a record context, make sure + // they occur in the same location in the context records. + if (Optional<unsigned> Index1 = + StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(D1)) { + if (Optional<unsigned> Index2 = + StructuralEquivalenceContext::findUntaggedStructOrUnionIndex( + D2)) { + if (*Index1 != *Index2) + return false; + } + } + } + + // If both declarations are class template specializations, we know + // the ODR applies, so check the template and template arguments. + ClassTemplateSpecializationDecl *Spec1 = + dyn_cast<ClassTemplateSpecializationDecl>(D1); + ClassTemplateSpecializationDecl *Spec2 = + dyn_cast<ClassTemplateSpecializationDecl>(D2); + if (Spec1 && Spec2) { + // Check that the specialized templates are the same. + if (!IsStructurallyEquivalent(Context, Spec1->getSpecializedTemplate(), + Spec2->getSpecializedTemplate())) + return false; + + // Check that the template arguments are the same. + if (Spec1->getTemplateArgs().size() != Spec2->getTemplateArgs().size()) + return false; + + for (unsigned I = 0, N = Spec1->getTemplateArgs().size(); I != N; ++I) + if (!IsStructurallyEquivalent(Context, Spec1->getTemplateArgs().get(I), + Spec2->getTemplateArgs().get(I))) + return false; + } + // If one is a class template specialization and the other is not, these + // structures are different. + else if (Spec1 || Spec2) + return false; + + // Compare the definitions of these two records. If either or both are + // incomplete, we assume that they are equivalent. + D1 = D1->getDefinition(); + D2 = D2->getDefinition(); + if (!D1 || !D2) + return true; + + if (CXXRecordDecl *D1CXX = dyn_cast<CXXRecordDecl>(D1)) { + if (CXXRecordDecl *D2CXX = dyn_cast<CXXRecordDecl>(D2)) { + if (D1CXX->hasExternalLexicalStorage() && + !D1CXX->isCompleteDefinition()) { + D1CXX->getASTContext().getExternalSource()->CompleteType(D1CXX); + } + + if (D1CXX->getNumBases() != D2CXX->getNumBases()) { + if (Context.Complain) { + Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) + << Context.ToCtx.getTypeDeclType(D2); + Context.Diag2(D2->getLocation(), diag::note_odr_number_of_bases) + << D2CXX->getNumBases(); + Context.Diag1(D1->getLocation(), diag::note_odr_number_of_bases) + << D1CXX->getNumBases(); + } + return false; + } + + // Check the base classes. + for (CXXRecordDecl::base_class_iterator Base1 = D1CXX->bases_begin(), + BaseEnd1 = D1CXX->bases_end(), + Base2 = D2CXX->bases_begin(); + Base1 != BaseEnd1; ++Base1, ++Base2) { + if (!IsStructurallyEquivalent(Context, Base1->getType(), + Base2->getType())) { + if (Context.Complain) { + Context.Diag2(D2->getLocation(), + diag::warn_odr_tag_type_inconsistent) + << Context.ToCtx.getTypeDeclType(D2); + Context.Diag2(Base2->getLocStart(), diag::note_odr_base) + << Base2->getType() << Base2->getSourceRange(); + Context.Diag1(Base1->getLocStart(), diag::note_odr_base) + << Base1->getType() << Base1->getSourceRange(); + } + return false; + } + + // Check virtual vs. non-virtual inheritance mismatch. + if (Base1->isVirtual() != Base2->isVirtual()) { + if (Context.Complain) { + Context.Diag2(D2->getLocation(), + diag::warn_odr_tag_type_inconsistent) + << Context.ToCtx.getTypeDeclType(D2); + Context.Diag2(Base2->getLocStart(), diag::note_odr_virtual_base) + << Base2->isVirtual() << Base2->getSourceRange(); + Context.Diag1(Base1->getLocStart(), diag::note_odr_base) + << Base1->isVirtual() << Base1->getSourceRange(); + } + return false; + } + } + } else if (D1CXX->getNumBases() > 0) { + if (Context.Complain) { + Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) + << Context.ToCtx.getTypeDeclType(D2); + const CXXBaseSpecifier *Base1 = D1CXX->bases_begin(); + Context.Diag1(Base1->getLocStart(), diag::note_odr_base) + << Base1->getType() << Base1->getSourceRange(); + Context.Diag2(D2->getLocation(), diag::note_odr_missing_base); + } + return false; + } + } + + // Check the fields for consistency. + RecordDecl::field_iterator Field2 = D2->field_begin(), + Field2End = D2->field_end(); + for (RecordDecl::field_iterator Field1 = D1->field_begin(), + Field1End = D1->field_end(); + Field1 != Field1End; ++Field1, ++Field2) { + if (Field2 == Field2End) { + if (Context.Complain) { + Context.Diag2(D2->getLocation(), + Context.ErrorOnTagTypeMismatch + ? diag::err_odr_tag_type_inconsistent + : diag::warn_odr_tag_type_inconsistent) + << Context.ToCtx.getTypeDeclType(D2); + Context.Diag1(Field1->getLocation(), diag::note_odr_field) + << Field1->getDeclName() << Field1->getType(); + Context.Diag2(D2->getLocation(), diag::note_odr_missing_field); + } + return false; + } + + if (!IsStructurallyEquivalent(Context, *Field1, *Field2)) + return false; + } + + if (Field2 != Field2End) { + if (Context.Complain) { + Context.Diag2(D2->getLocation(), + Context.ErrorOnTagTypeMismatch + ? diag::err_odr_tag_type_inconsistent + : diag::warn_odr_tag_type_inconsistent) + << Context.ToCtx.getTypeDeclType(D2); + Context.Diag2(Field2->getLocation(), diag::note_odr_field) + << Field2->getDeclName() << Field2->getType(); + Context.Diag1(D1->getLocation(), diag::note_odr_missing_field); + } + return false; + } + + return true; +} + +/// Determine structural equivalence of two enums. +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + EnumDecl *D1, EnumDecl *D2) { + EnumDecl::enumerator_iterator EC2 = D2->enumerator_begin(), + EC2End = D2->enumerator_end(); + for (EnumDecl::enumerator_iterator EC1 = D1->enumerator_begin(), + EC1End = D1->enumerator_end(); + EC1 != EC1End; ++EC1, ++EC2) { + if (EC2 == EC2End) { + if (Context.Complain) { + Context.Diag2(D2->getLocation(), + Context.ErrorOnTagTypeMismatch + ? diag::err_odr_tag_type_inconsistent + : diag::warn_odr_tag_type_inconsistent) + << Context.ToCtx.getTypeDeclType(D2); + Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator) + << EC1->getDeclName() << EC1->getInitVal().toString(10); + Context.Diag2(D2->getLocation(), diag::note_odr_missing_enumerator); + } + return false; + } + + llvm::APSInt Val1 = EC1->getInitVal(); + llvm::APSInt Val2 = EC2->getInitVal(); + if (!llvm::APSInt::isSameValue(Val1, Val2) || + !IsStructurallyEquivalent(EC1->getIdentifier(), EC2->getIdentifier())) { + if (Context.Complain) { + Context.Diag2(D2->getLocation(), + Context.ErrorOnTagTypeMismatch + ? diag::err_odr_tag_type_inconsistent + : diag::warn_odr_tag_type_inconsistent) + << Context.ToCtx.getTypeDeclType(D2); + Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator) + << EC2->getDeclName() << EC2->getInitVal().toString(10); + Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator) + << EC1->getDeclName() << EC1->getInitVal().toString(10); + } + return false; + } + } + + if (EC2 != EC2End) { + if (Context.Complain) { + Context.Diag2(D2->getLocation(), + Context.ErrorOnTagTypeMismatch + ? diag::err_odr_tag_type_inconsistent + : diag::warn_odr_tag_type_inconsistent) + << Context.ToCtx.getTypeDeclType(D2); + Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator) + << EC2->getDeclName() << EC2->getInitVal().toString(10); + Context.Diag1(D1->getLocation(), diag::note_odr_missing_enumerator); + } + return false; + } + + return true; +} + +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + TemplateParameterList *Params1, + TemplateParameterList *Params2) { + if (Params1->size() != Params2->size()) { + if (Context.Complain) { + Context.Diag2(Params2->getTemplateLoc(), + diag::err_odr_different_num_template_parameters) + << Params1->size() << Params2->size(); + Context.Diag1(Params1->getTemplateLoc(), + diag::note_odr_template_parameter_list); + } + return false; + } + + for (unsigned I = 0, N = Params1->size(); I != N; ++I) { + if (Params1->getParam(I)->getKind() != Params2->getParam(I)->getKind()) { + if (Context.Complain) { + Context.Diag2(Params2->getParam(I)->getLocation(), + diag::err_odr_different_template_parameter_kind); + Context.Diag1(Params1->getParam(I)->getLocation(), + diag::note_odr_template_parameter_here); + } + return false; + } + + if (!Context.IsStructurallyEquivalent(Params1->getParam(I), + Params2->getParam(I))) { + + return false; + } + } + + return true; +} + +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + TemplateTypeParmDecl *D1, + TemplateTypeParmDecl *D2) { + if (D1->isParameterPack() != D2->isParameterPack()) { + if (Context.Complain) { + Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack) + << D2->isParameterPack(); + Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack) + << D1->isParameterPack(); + } + return false; + } + + return true; +} + +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + NonTypeTemplateParmDecl *D1, + NonTypeTemplateParmDecl *D2) { + if (D1->isParameterPack() != D2->isParameterPack()) { + if (Context.Complain) { + Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack) + << D2->isParameterPack(); + Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack) + << D1->isParameterPack(); + } + return false; + } + + // Check types. + if (!Context.IsStructurallyEquivalent(D1->getType(), D2->getType())) { + if (Context.Complain) { + Context.Diag2(D2->getLocation(), + diag::err_odr_non_type_parameter_type_inconsistent) + << D2->getType() << D1->getType(); + Context.Diag1(D1->getLocation(), diag::note_odr_value_here) + << D1->getType(); + } + return false; + } + + return true; +} + +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + TemplateTemplateParmDecl *D1, + TemplateTemplateParmDecl *D2) { + if (D1->isParameterPack() != D2->isParameterPack()) { + if (Context.Complain) { + Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack) + << D2->isParameterPack(); + Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack) + << D1->isParameterPack(); + } + return false; + } + + // Check template parameter lists. + return IsStructurallyEquivalent(Context, D1->getTemplateParameters(), + D2->getTemplateParameters()); +} + +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + ClassTemplateDecl *D1, + ClassTemplateDecl *D2) { + // Check template parameters. + if (!IsStructurallyEquivalent(Context, D1->getTemplateParameters(), + D2->getTemplateParameters())) + return false; + + // Check the templated declaration. + return Context.IsStructurallyEquivalent(D1->getTemplatedDecl(), + D2->getTemplatedDecl()); +} + +/// Determine structural equivalence of two declarations. +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + Decl *D1, Decl *D2) { + // FIXME: Check for known structural equivalences via a callback of some sort. + + // Check whether we already know that these two declarations are not + // structurally equivalent. + if (Context.NonEquivalentDecls.count( + std::make_pair(D1->getCanonicalDecl(), D2->getCanonicalDecl()))) + return false; + + // Determine whether we've already produced a tentative equivalence for D1. + Decl *&EquivToD1 = Context.TentativeEquivalences[D1->getCanonicalDecl()]; + if (EquivToD1) + return EquivToD1 == D2->getCanonicalDecl(); + + // Produce a tentative equivalence D1 <-> D2, which will be checked later. + EquivToD1 = D2->getCanonicalDecl(); + Context.DeclsToCheck.push_back(D1->getCanonicalDecl()); + return true; +} +} // namespace + +namespace clang { + +DiagnosticBuilder StructuralEquivalenceContext::Diag1(SourceLocation Loc, + unsigned DiagID) { + assert(Complain && "Not allowed to complain"); + if (LastDiagFromC2) + FromCtx.getDiagnostics().notePriorDiagnosticFrom(ToCtx.getDiagnostics()); + LastDiagFromC2 = false; + return FromCtx.getDiagnostics().Report(Loc, DiagID); +} + +DiagnosticBuilder StructuralEquivalenceContext::Diag2(SourceLocation Loc, + unsigned DiagID) { + assert(Complain && "Not allowed to complain"); + if (!LastDiagFromC2) + ToCtx.getDiagnostics().notePriorDiagnosticFrom(FromCtx.getDiagnostics()); + LastDiagFromC2 = true; + return ToCtx.getDiagnostics().Report(Loc, DiagID); +} + +Optional<unsigned> +StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(RecordDecl *Anon) { + ASTContext &Context = Anon->getASTContext(); + QualType AnonTy = Context.getRecordType(Anon); + + RecordDecl *Owner = dyn_cast<RecordDecl>(Anon->getDeclContext()); + if (!Owner) + return None; + + unsigned Index = 0; + for (const auto *D : Owner->noload_decls()) { + const auto *F = dyn_cast<FieldDecl>(D); + if (!F) + continue; + + if (F->isAnonymousStructOrUnion()) { + if (Context.hasSameType(F->getType(), AnonTy)) + break; + ++Index; + continue; + } + + // If the field looks like this: + // struct { ... } A; + QualType FieldType = F->getType(); + if (const auto *RecType = dyn_cast<RecordType>(FieldType)) { + const RecordDecl *RecDecl = RecType->getDecl(); + if (RecDecl->getDeclContext() == Owner && !RecDecl->getIdentifier()) { + if (Context.hasSameType(FieldType, AnonTy)) + break; + ++Index; + continue; + } + } + } + + return Index; +} + +bool StructuralEquivalenceContext::IsStructurallyEquivalent(Decl *D1, + Decl *D2) { + if (!::IsStructurallyEquivalent(*this, D1, D2)) + return false; + + return !Finish(); +} + +bool StructuralEquivalenceContext::IsStructurallyEquivalent(QualType T1, + QualType T2) { + if (!::IsStructurallyEquivalent(*this, T1, T2)) + return false; + + return !Finish(); +} + +bool StructuralEquivalenceContext::Finish() { + while (!DeclsToCheck.empty()) { + // Check the next declaration. + Decl *D1 = DeclsToCheck.front(); + DeclsToCheck.pop_front(); + + Decl *D2 = TentativeEquivalences[D1]; + assert(D2 && "Unrecorded tentative equivalence?"); + + bool Equivalent = true; + + // FIXME: Switch on all declaration kinds. For now, we're just going to + // check the obvious ones. + if (RecordDecl *Record1 = dyn_cast<RecordDecl>(D1)) { + if (RecordDecl *Record2 = dyn_cast<RecordDecl>(D2)) { + // Check for equivalent structure names. + IdentifierInfo *Name1 = Record1->getIdentifier(); + if (!Name1 && Record1->getTypedefNameForAnonDecl()) + Name1 = Record1->getTypedefNameForAnonDecl()->getIdentifier(); + IdentifierInfo *Name2 = Record2->getIdentifier(); + if (!Name2 && Record2->getTypedefNameForAnonDecl()) + Name2 = Record2->getTypedefNameForAnonDecl()->getIdentifier(); + if (!::IsStructurallyEquivalent(Name1, Name2) || + !::IsStructurallyEquivalent(*this, Record1, Record2)) + Equivalent = false; + } else { + // Record/non-record mismatch. + Equivalent = false; + } + } else if (EnumDecl *Enum1 = dyn_cast<EnumDecl>(D1)) { + if (EnumDecl *Enum2 = dyn_cast<EnumDecl>(D2)) { + // Check for equivalent enum names. + IdentifierInfo *Name1 = Enum1->getIdentifier(); + if (!Name1 && Enum1->getTypedefNameForAnonDecl()) + Name1 = Enum1->getTypedefNameForAnonDecl()->getIdentifier(); + IdentifierInfo *Name2 = Enum2->getIdentifier(); + if (!Name2 && Enum2->getTypedefNameForAnonDecl()) + Name2 = Enum2->getTypedefNameForAnonDecl()->getIdentifier(); + if (!::IsStructurallyEquivalent(Name1, Name2) || + !::IsStructurallyEquivalent(*this, Enum1, Enum2)) + Equivalent = false; + } else { + // Enum/non-enum mismatch + Equivalent = false; + } + } else if (TypedefNameDecl *Typedef1 = dyn_cast<TypedefNameDecl>(D1)) { + if (TypedefNameDecl *Typedef2 = dyn_cast<TypedefNameDecl>(D2)) { + if (!::IsStructurallyEquivalent(Typedef1->getIdentifier(), + Typedef2->getIdentifier()) || + !::IsStructurallyEquivalent(*this, Typedef1->getUnderlyingType(), + Typedef2->getUnderlyingType())) + Equivalent = false; + } else { + // Typedef/non-typedef mismatch. + Equivalent = false; + } + } else if (ClassTemplateDecl *ClassTemplate1 = + dyn_cast<ClassTemplateDecl>(D1)) { + if (ClassTemplateDecl *ClassTemplate2 = dyn_cast<ClassTemplateDecl>(D2)) { + if (!::IsStructurallyEquivalent(ClassTemplate1->getIdentifier(), + ClassTemplate2->getIdentifier()) || + !::IsStructurallyEquivalent(*this, ClassTemplate1, ClassTemplate2)) + Equivalent = false; + } else { + // Class template/non-class-template mismatch. + Equivalent = false; + } + } else if (TemplateTypeParmDecl *TTP1 = + dyn_cast<TemplateTypeParmDecl>(D1)) { + if (TemplateTypeParmDecl *TTP2 = dyn_cast<TemplateTypeParmDecl>(D2)) { + if (!::IsStructurallyEquivalent(*this, TTP1, TTP2)) + Equivalent = false; + } else { + // Kind mismatch. + Equivalent = false; + } + } else if (NonTypeTemplateParmDecl *NTTP1 = + dyn_cast<NonTypeTemplateParmDecl>(D1)) { + if (NonTypeTemplateParmDecl *NTTP2 = + dyn_cast<NonTypeTemplateParmDecl>(D2)) { + if (!::IsStructurallyEquivalent(*this, NTTP1, NTTP2)) + Equivalent = false; + } else { + // Kind mismatch. + Equivalent = false; + } + } else if (TemplateTemplateParmDecl *TTP1 = + dyn_cast<TemplateTemplateParmDecl>(D1)) { + if (TemplateTemplateParmDecl *TTP2 = + dyn_cast<TemplateTemplateParmDecl>(D2)) { + if (!::IsStructurallyEquivalent(*this, TTP1, TTP2)) + Equivalent = false; + } else { + // Kind mismatch. + Equivalent = false; + } + } + + if (!Equivalent) { + // Note that these two declarations are not equivalent (and we already + // know about it). + NonEquivalentDecls.insert( + std::make_pair(D1->getCanonicalDecl(), D2->getCanonicalDecl())); + return true; + } + // FIXME: Check other declaration kinds! + } + + return false; +} +} // namespace clang diff --git a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp index a97d6a2..fc4d8b1 100644 --- a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp @@ -13,6 +13,7 @@ #include "clang/AST/CXXInheritance.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/RecordLayout.h" #include "llvm/ADT/SetVector.h" #include <algorithm> @@ -56,6 +57,7 @@ bool CXXBasePaths::isAmbiguous(CanQualType BaseType) { void CXXBasePaths::clear() { Paths.clear(); ClassSubobjects.clear(); + VisitedDependentRecords.clear(); ScratchPath.clear(); DetectedVirtual = nullptr; } @@ -66,6 +68,7 @@ void CXXBasePaths::swap(CXXBasePaths &Other) { std::swap(Origin, Other.Origin); Paths.swap(Other.Paths); ClassSubobjects.swap(Other.ClassSubobjects); + VisitedDependentRecords.swap(Other.VisitedDependentRecords); std::swap(FindAmbiguities, Other.FindAmbiguities); std::swap(RecordPaths, Other.RecordPaths); std::swap(DetectVirtual, Other.DetectVirtual); @@ -88,7 +91,7 @@ bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base, const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl(); // FIXME: Capturing 'this' is a workaround for name lookup bugs in GCC 4.7. return lookupInBases( - [this, BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { + [BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { return FindBaseClass(Specifier, Path, BaseDecl); }, Paths); @@ -109,7 +112,7 @@ bool CXXRecordDecl::isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const { const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl(); // FIXME: Capturing 'this' is a workaround for name lookup bugs in GCC 4.7. return lookupInBases( - [this, BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { + [BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { return FindVirtualBaseClass(Specifier, Path, BaseDecl); }, Paths); @@ -174,9 +177,10 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches, return AllMatches; } -bool CXXBasePaths::lookupInBases( - ASTContext &Context, const CXXRecordDecl *Record, - CXXRecordDecl::BaseMatchesCallback BaseMatches) { +bool CXXBasePaths::lookupInBases(ASTContext &Context, + const CXXRecordDecl *Record, + CXXRecordDecl::BaseMatchesCallback BaseMatches, + bool LookupInDependent) { bool FoundPath = false; // The access of the path down to this record. @@ -194,7 +198,7 @@ bool CXXBasePaths::lookupInBases( // the base class scope is not examined during unqualified name lookup // either at the point of definition of the class template or member or // during an instantiation of the class tem- plate or member. - if (BaseType->isDependentType()) + if (!LookupInDependent && BaseType->isDependentType()) continue; // Determine whether we need to visit this base class at all, @@ -262,10 +266,34 @@ bool CXXBasePaths::lookupInBases( return FoundPath; } } else if (VisitBase) { - CXXRecordDecl *BaseRecord - = cast<CXXRecordDecl>(BaseSpec.getType()->castAs<RecordType>() - ->getDecl()); - if (lookupInBases(Context, BaseRecord, BaseMatches)) { + CXXRecordDecl *BaseRecord; + if (LookupInDependent) { + BaseRecord = nullptr; + const TemplateSpecializationType *TST = + BaseSpec.getType()->getAs<TemplateSpecializationType>(); + if (!TST) { + if (auto *RT = BaseSpec.getType()->getAs<RecordType>()) + BaseRecord = cast<CXXRecordDecl>(RT->getDecl()); + } else { + TemplateName TN = TST->getTemplateName(); + if (auto *TD = + dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) + BaseRecord = TD->getTemplatedDecl(); + } + if (BaseRecord) { + if (!BaseRecord->hasDefinition() || + VisitedDependentRecords.count(BaseRecord)) { + BaseRecord = nullptr; + } else { + VisitedDependentRecords.insert(BaseRecord); + } + } + } else { + BaseRecord = cast<CXXRecordDecl>( + BaseSpec.getType()->castAs<RecordType>()->getDecl()); + } + if (BaseRecord && + lookupInBases(Context, BaseRecord, BaseMatches, LookupInDependent)) { // C++ [class.member.lookup]p2: // A member name f in one sub-object B hides a member name f in // a sub-object A if A is a base class sub-object of B. Any @@ -299,9 +327,11 @@ bool CXXBasePaths::lookupInBases( } bool CXXRecordDecl::lookupInBases(BaseMatchesCallback BaseMatches, - CXXBasePaths &Paths) const { + CXXBasePaths &Paths, + bool LookupInDependent) const { // If we didn't find anything, report that. - if (!Paths.lookupInBases(getASTContext(), this, BaseMatches)) + if (!Paths.lookupInBases(getASTContext(), this, BaseMatches, + LookupInDependent)) return false; // If we're not recording paths or we won't ever find ambiguities, @@ -387,23 +417,49 @@ bool CXXRecordDecl::FindTagMember(const CXXBaseSpecifier *Specifier, return false; } -bool CXXRecordDecl::FindOrdinaryMember(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, - DeclarationName Name) { - RecordDecl *BaseRecord = - Specifier->getType()->castAs<RecordType>()->getDecl(); - - const unsigned IDNS = IDNS_Ordinary | IDNS_Tag | IDNS_Member; +static bool findOrdinaryMember(RecordDecl *BaseRecord, CXXBasePath &Path, + DeclarationName Name) { + const unsigned IDNS = clang::Decl::IDNS_Ordinary | clang::Decl::IDNS_Tag | + clang::Decl::IDNS_Member; for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); Path.Decls = Path.Decls.slice(1)) { if (Path.Decls.front()->isInIdentifierNamespace(IDNS)) return true; } - + return false; } +bool CXXRecordDecl::FindOrdinaryMember(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, + DeclarationName Name) { + RecordDecl *BaseRecord = + Specifier->getType()->castAs<RecordType>()->getDecl(); + return findOrdinaryMember(BaseRecord, Path, Name); +} + +bool CXXRecordDecl::FindOrdinaryMemberInDependentClasses( + const CXXBaseSpecifier *Specifier, CXXBasePath &Path, + DeclarationName Name) { + const TemplateSpecializationType *TST = + Specifier->getType()->getAs<TemplateSpecializationType>(); + if (!TST) { + auto *RT = Specifier->getType()->getAs<RecordType>(); + if (!RT) + return false; + return findOrdinaryMember(RT->getDecl(), Path, Name); + } + TemplateName TN = TST->getTemplateName(); + const auto *TD = dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl()); + if (!TD) + return false; + CXXRecordDecl *RD = TD->getTemplatedDecl(); + if (!RD) + return false; + return findOrdinaryMember(RD, Path, Name); +} + bool CXXRecordDecl::FindOMPReductionMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name) { @@ -438,6 +494,36 @@ FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, return false; } +std::vector<const NamedDecl *> CXXRecordDecl::lookupDependentName( + const DeclarationName &Name, + llvm::function_ref<bool(const NamedDecl *ND)> Filter) { + std::vector<const NamedDecl *> Results; + // Lookup in the class. + DeclContext::lookup_result DirectResult = lookup(Name); + if (!DirectResult.empty()) { + for (const NamedDecl *ND : DirectResult) { + if (Filter(ND)) + Results.push_back(ND); + } + return Results; + } + // Perform lookup into our base classes. + CXXBasePaths Paths; + Paths.setOrigin(this); + if (!lookupInBases( + [&](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { + return CXXRecordDecl::FindOrdinaryMemberInDependentClasses( + Specifier, Path, Name); + }, + Paths, /*LookupInDependent=*/true)) + return Results; + for (const NamedDecl *ND : Paths.front().Decls) { + if (Filter(ND)) + Results.push_back(ND); + } + return Results; +} + void OverridingMethods::add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding) { SmallVectorImpl<UniqueVirtualMethod> &SubobjectOverrides diff --git a/contrib/llvm/tools/clang/lib/AST/Comment.cpp b/contrib/llvm/tools/clang/lib/AST/Comment.cpp index 7a7d3dd..dfa2a16 100644 --- a/contrib/llvm/tools/clang/lib/AST/Comment.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Comment.cpp @@ -116,6 +116,9 @@ bool ParagraphComment::isWhitespaceNoCache() const { static TypeLoc lookThroughTypedefOrTypeAliasLocs(TypeLoc &SrcTL) { TypeLoc TL = SrcTL.IgnoreParens(); + // Look through attribute types. + if (AttributedTypeLoc AttributeTL = TL.getAs<AttributedTypeLoc>()) + return AttributeTL.getModifiedLoc(); // Look through qualified types. if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) return QualifiedTL.getUnqualifiedLoc(); @@ -280,8 +283,25 @@ void DeclInfo::fill() { case Decl::EnumConstant: case Decl::ObjCIvar: case Decl::ObjCAtDefsField: + case Decl::ObjCProperty: { + const TypeSourceInfo *TSI; + if (const auto *VD = dyn_cast<DeclaratorDecl>(CommentDecl)) + TSI = VD->getTypeSourceInfo(); + else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(CommentDecl)) + TSI = PD->getTypeSourceInfo(); + else + TSI = nullptr; + if (TSI) { + TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc(); + FunctionTypeLoc FTL; + if (getFunctionTypeLoc(TL, FTL)) { + ParamVars = FTL.getParams(); + ReturnType = FTL.getReturnLoc().getType(); + } + } Kind = VariableKind; break; + } case Decl::Namespace: Kind = NamespaceKind; break; diff --git a/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp b/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp index d39a9b2..403454d 100644 --- a/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp @@ -86,7 +86,7 @@ ParamCommandComment *Sema::actOnParamCommandStart( new (Allocator) ParamCommandComment(LocBegin, LocEnd, CommandID, CommandMarker); - if (!isFunctionDecl()) + if (!isFunctionDecl() && !isFunctionOrBlockPointerVarLikeDecl()) Diag(Command->getLocation(), diag::warn_doc_param_not_attached_to_a_function_decl) << CommandMarker @@ -584,7 +584,11 @@ void Sema::checkReturnsCommand(const BlockCommandComment *Command) { assert(ThisDeclInfo && "should not call this check on a bare comment"); - if (isFunctionDecl()) { + // We allow the return command for all @properties because it can be used + // to document the value that the property getter returns. + if (isObjCPropertyDecl()) + return; + if (isFunctionDecl() || isFunctionOrBlockPointerVarLikeDecl()) { if (ThisDeclInfo->ReturnType->isVoidType()) { unsigned DiagKind; switch (ThisDeclInfo->CommentDecl->getKind()) { @@ -610,8 +614,6 @@ void Sema::checkReturnsCommand(const BlockCommandComment *Command) { } return; } - else if (isObjCPropertyDecl()) - return; Diag(Command->getLocation(), diag::warn_doc_returns_not_attached_to_a_function_decl) @@ -844,6 +846,30 @@ bool Sema::isFunctionPointerVarDecl() { return false; } +bool Sema::isFunctionOrBlockPointerVarLikeDecl() { + if (!ThisDeclInfo) + return false; + if (!ThisDeclInfo->IsFilled) + inspectThisDecl(); + if (ThisDeclInfo->getKind() != DeclInfo::VariableKind || + !ThisDeclInfo->CurrentDecl) + return false; + QualType QT; + if (const auto *VD = dyn_cast<DeclaratorDecl>(ThisDeclInfo->CurrentDecl)) + QT = VD->getType(); + else if (const auto *PD = + dyn_cast<ObjCPropertyDecl>(ThisDeclInfo->CurrentDecl)) + QT = PD->getType(); + else + return false; + // We would like to warn about the 'returns'/'param' commands for + // variables that don't directly specify the function type, so type aliases + // can be ignored. + if (QT->getAs<TypedefType>()) + return false; + return QT->isFunctionPointerType() || QT->isBlockPointerType(); +} + bool Sema::isObjCPropertyDecl() { if (!ThisDeclInfo) return false; diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp index 81f0878..573a98e 100644 --- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp @@ -47,9 +47,7 @@ bool Decl::isOutOfLine() const { TranslationUnitDecl::TranslationUnitDecl(ASTContext &ctx) : Decl(TranslationUnit, nullptr, SourceLocation()), - DeclContext(TranslationUnit), Ctx(ctx), AnonymousNamespace(nullptr) { - Hidden = Ctx.getLangOpts().ModulesLocalVisibility; -} + DeclContext(TranslationUnit), Ctx(ctx), AnonymousNamespace(nullptr) {} //===----------------------------------------------------------------------===// // NamedDecl Implementation @@ -575,6 +573,44 @@ static bool isSingleLineLanguageLinkage(const Decl &D) { return false; } +static bool isExportedFromModuleIntefaceUnit(const NamedDecl *D) { + switch (D->getModuleOwnershipKind()) { + case Decl::ModuleOwnershipKind::Unowned: + case Decl::ModuleOwnershipKind::ModulePrivate: + return false; + case Decl::ModuleOwnershipKind::Visible: + case Decl::ModuleOwnershipKind::VisibleWhenImported: + if (auto *M = D->getOwningModule()) + return M->Kind == Module::ModuleInterfaceUnit; + } + llvm_unreachable("unexpected module ownership kind"); +} + +static LinkageInfo getInternalLinkageFor(const NamedDecl *D) { + // Internal linkage declarations within a module interface unit are modeled + // as "module-internal linkage", which means that they have internal linkage + // formally but can be indirectly accessed from outside the module via inline + // functions and templates defined within the module. + if (auto *M = D->getOwningModule()) + if (M->Kind == Module::ModuleInterfaceUnit) + return LinkageInfo(ModuleInternalLinkage, DefaultVisibility, false); + + return LinkageInfo::internal(); +} + +static LinkageInfo getExternalLinkageFor(const NamedDecl *D) { + // C++ Modules TS [basic.link]/6.8: + // - A name declared at namespace scope that does not have internal linkage + // by the previous rules and that is introduced by a non-exported + // declaration has module linkage. + if (auto *M = D->getOwningModule()) + if (M->Kind == Module::ModuleInterfaceUnit) + if (!isExportedFromModuleIntefaceUnit(D)) + return LinkageInfo(ModuleLinkage, DefaultVisibility, false); + + return LinkageInfo::external(); +} + static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVComputationKind computation) { assert(D->getDeclContext()->getRedeclContext()->isFileContext() && @@ -590,16 +626,18 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, if (const auto *Var = dyn_cast<VarDecl>(D)) { // Explicitly declared static. if (Var->getStorageClass() == SC_Static) - return LinkageInfo::internal(); + return getInternalLinkageFor(Var); // - a non-inline, non-volatile object or reference that is explicitly // declared const or constexpr and neither explicitly declared extern // nor previously declared to have external linkage; or (there is no // equivalent in C99) + // The C++ modules TS adds "non-exported" to this list. if (Context.getLangOpts().CPlusPlus && Var->getType().isConstQualified() && !Var->getType().isVolatileQualified() && - !Var->isInline()) { + !Var->isInline() && + !isExportedFromModuleIntefaceUnit(Var)) { const VarDecl *PrevVar = Var->getPreviousDecl(); if (PrevVar) return getLVForDecl(PrevVar, computation); @@ -607,7 +645,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, if (Var->getStorageClass() != SC_Extern && Var->getStorageClass() != SC_PrivateExtern && !isSingleLineLanguageLinkage(*Var)) - return LinkageInfo::internal(); + return getInternalLinkageFor(Var); } for (const VarDecl *PrevVar = Var->getPreviousDecl(); PrevVar; @@ -617,7 +655,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, return PrevVar->getLinkageAndVisibility(); // Explicitly declared static. if (PrevVar->getStorageClass() == SC_Static) - return LinkageInfo::internal(); + return getInternalLinkageFor(Var); } } else if (const FunctionDecl *Function = D->getAsFunction()) { // C++ [temp]p4: @@ -626,7 +664,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // Explicitly declared static. if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) - return LinkageInfo(InternalLinkage, DefaultVisibility, false); + return getInternalLinkageFor(Function); } else if (const auto *IFD = dyn_cast<IndirectFieldDecl>(D)) { // - a data member of an anonymous union. const VarDecl *VD = IFD->getVarDecl(); @@ -639,7 +677,12 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, const auto *Var = dyn_cast<VarDecl>(D); const auto *Func = dyn_cast<FunctionDecl>(D); // FIXME: In C++11 onwards, anonymous namespaces should give decls - // within them internal linkage, not unique external linkage. + // within them (including those inside extern "C" contexts) internal + // linkage, not unique external linkage: + // + // C++11 [basic.link]p4: + // An unnamed namespace or a namespace declared directly or indirectly + // within an unnamed namespace has internal linkage. if ((!Var || !isFirstInExternCContext(Var)) && (!Func || !isFirstInExternCContext(Func))) return LinkageInfo::uniqueExternal(); @@ -720,7 +763,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // because of this, but unique-external linkage suits us. if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var)) { LinkageInfo TypeLV = getLVForType(*Var->getType(), computation); - if (TypeLV.getLinkage() != ExternalLinkage) + if (TypeLV.getLinkage() != ExternalLinkage && + TypeLV.getLinkage() != ModuleLinkage) return LinkageInfo::uniqueExternal(); if (!LV.isVisibilityExplicit()) LV.mergeVisibility(TypeLV); @@ -818,7 +862,9 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // - a namespace (7.3), unless it is declared within an unnamed // namespace. - } else if (isa<NamespaceDecl>(D) && !D->isInAnonymousNamespace()) { + // + // We handled names in anonymous namespaces above. + } else if (isa<NamespaceDecl>(D)) { return LV; // By extension, we assign external linkage to Objective-C @@ -1127,6 +1173,8 @@ static LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl, if (const auto *ND = dyn_cast<NamedDecl>(DC)) return getLVForDecl(ND, computation); + // FIXME: We have a closure at TU scope with no context declaration. This + // should probably have no linkage. return LinkageInfo::external(); } @@ -1139,7 +1187,7 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D, // This is a "void f();" which got merged with a file static. if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) - return LinkageInfo::internal(); + return getInternalLinkageFor(Function); LinkageInfo LV; if (!hasExplicitVisibilityAlready(computation)) { @@ -1228,7 +1276,7 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D, LVComputationKind computation) { // Internal_linkage attribute overrides other considerations. if (D->hasAttr<InternalLinkageAttr>()) - return LinkageInfo::internal(); + return getInternalLinkageFor(D); // Objective-C: treat all Objective-C declarations as having external // linkage. @@ -1253,14 +1301,15 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D, case Decl::EnumConstant: // C++ [basic.link]p4: an enumerator has the linkage of its enumeration. - return getLVForDecl(cast<EnumDecl>(D->getDeclContext()), computation); + if (D->getASTContext().getLangOpts().CPlusPlus) + return getLVForDecl(cast<EnumDecl>(D->getDeclContext()), computation); + return LinkageInfo::visible_none(); case Decl::Typedef: case Decl::TypeAlias: // A typedef declaration has linkage if it gives a type a name for // linkage purposes. - if (!D->getASTContext().getLangOpts().CPlusPlus || - !cast<TypedefNameDecl>(D) + if (!cast<TypedefNameDecl>(D) ->getAnonDeclWithTypedefName(/*AnyRedecl*/true)) return LinkageInfo::none(); break; @@ -1276,14 +1325,14 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D, case Decl::ObjCProperty: case Decl::ObjCPropertyImpl: case Decl::ObjCProtocol: - return LinkageInfo::external(); + return getExternalLinkageFor(D); case Decl::CXXRecord: { const auto *Record = cast<CXXRecordDecl>(D); if (Record->isLambda()) { if (!Record->getLambdaManglingNumber()) { // This lambda has no mangling number, so it's internal. - return LinkageInfo::internal(); + return getInternalLinkageFor(D); } // This lambda has its linkage/visibility determined: @@ -1299,7 +1348,7 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D, const CXXRecordDecl *OuterMostLambda = getOutermostEnclosingLambda(Record); if (!OuterMostLambda->getLambdaManglingNumber()) - return LinkageInfo::internal(); + return getInternalLinkageFor(D); return getLVForClosure( OuterMostLambda->getDeclContext()->getRedeclContext(), @@ -1350,7 +1399,7 @@ public: LVComputationKind computation) { // Internal_linkage attribute overrides other considerations. if (D->hasAttr<InternalLinkageAttr>()) - return LinkageInfo::internal(); + return getInternalLinkageFor(D); if (computation == LVForLinkageOnly && D->hasCachedLinkage()) return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false); @@ -1414,6 +1463,11 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, const PrintingPolicy &P) const { const DeclContext *Ctx = getDeclContext(); + // For ObjC methods, look through categories and use the interface as context. + if (auto *MD = dyn_cast<ObjCMethodDecl>(this)) + if (auto *ID = MD->getClassInterface()) + Ctx = ID; + if (Ctx->isFunctionOrMethod()) { printName(OS); return; @@ -2143,13 +2197,6 @@ APValue *VarDecl::evaluateValue() const { return evaluateValue(Notes); } -namespace { -// Destroy an APValue that was allocated in an ASTContext. -void DestroyAPValue(void* UntypedValue) { - static_cast<APValue*>(UntypedValue)->~APValue(); -} -} // namespace - APValue *VarDecl::evaluateValue( SmallVectorImpl<PartialDiagnosticAt> &Notes) const { EvaluatedStmt *Eval = ensureEvaluatedStmt(); @@ -2181,7 +2228,7 @@ APValue *VarDecl::evaluateValue( if (!Result) Eval->Evaluated = APValue(); else if (Eval->Evaluated.needsCleanup()) - getASTContext().AddDeallocation(DestroyAPValue, &Eval->Evaluated); + getASTContext().addDestruction(&Eval->Evaluated); Eval->IsEvaluating = false; Eval->WasEvaluated = true; @@ -2253,6 +2300,14 @@ bool VarDecl::checkInitIsICE() const { return Eval->IsICE; } +template<typename DeclT> +static DeclT *getDefinitionOrSelf(DeclT *D) { + assert(D); + if (auto *Def = D->getDefinition()) + return Def; + return D; +} + VarDecl *VarDecl::getTemplateInstantiationPattern() const { // If it's a variable template specialization, find the template or partial // specialization from which it was instantiated. @@ -2264,7 +2319,7 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const { break; VTD = NewVTD; } - return VTD->getTemplatedDecl()->getDefinition(); + return getDefinitionOrSelf(VTD->getTemplatedDecl()); } if (auto *VTPSD = From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) { @@ -2273,7 +2328,7 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const { break; VTPSD = NewVTPSD; } - return VTPSD->getDefinition(); + return getDefinitionOrSelf<VarDecl>(VTPSD); } } @@ -2282,23 +2337,18 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const { VarDecl *VD = getInstantiatedFromStaticDataMember(); while (auto *NewVD = VD->getInstantiatedFromStaticDataMember()) VD = NewVD; - return VD->getDefinition(); + return getDefinitionOrSelf(VD); } } 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 getDefinitionOrSelf(VarTemplate->getTemplatedDecl()); } return nullptr; } @@ -2510,7 +2560,7 @@ bool FunctionDecl::isVariadic() const { bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const { for (auto I : redecls()) { - if (I->Body || I->IsLateTemplateParsed) { + if (I->doesThisDeclarationHaveABody()) { Definition = I; return true; } @@ -2535,9 +2585,8 @@ bool FunctionDecl::hasTrivialBody() const bool FunctionDecl::isDefined(const FunctionDecl *&Definition) const { for (auto I : redecls()) { - if (I->IsDeleted || I->IsDefaulted || I->Body || I->IsLateTemplateParsed || - I->hasDefiningAttr()) { - Definition = I->IsDeleted ? I->getCanonicalDecl() : I; + if (I->isThisDeclarationADefinition()) { + Definition = I; return true; } } @@ -2632,7 +2681,7 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const { return (proto->getParamType(1).getCanonicalType() == Context.VoidPtrTy); } -bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { +bool FunctionDecl::isReplaceableGlobalAllocationFunction(bool *IsAligned) const { if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName) return false; if (getDeclName().getCXXOverloadedOperator() != OO_New && @@ -2678,8 +2727,11 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { // In C++17, the next parameter can be a 'std::align_val_t' for aligned // new/delete. - if (Ctx.getLangOpts().AlignedAllocation && !Ty.isNull() && Ty->isAlignValT()) + if (Ctx.getLangOpts().AlignedAllocation && !Ty.isNull() && Ty->isAlignValT()) { + if (IsAligned) + *IsAligned = true; Consume(); + } // Finally, if this is not a sized delete, the final parameter can // be a 'const std::nothrow_t&'. @@ -3005,9 +3057,7 @@ SourceRange FunctionDecl::getExceptionSpecSourceRange() const { const Attr *FunctionDecl::getUnusedResultAttr() const { QualType RetType = getReturnType(); if (RetType->isRecordType()) { - const CXXRecordDecl *Ret = RetType->getAsCXXRecordDecl(); - const auto *MD = dyn_cast<CXXMethodDecl>(this); - if (Ret && !(MD && MD->getCorrespondingMethodInClass(Ret, true))) { + if (const CXXRecordDecl *Ret = RetType->getAsCXXRecordDecl()) { if (const auto *R = Ret->getAttr<WarnUnusedResultAttr>()) return R; } @@ -3202,9 +3252,12 @@ bool FunctionDecl::isTemplateInstantiation() const { FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const { // Handle class scope explicit specialization special case. - if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) - return getClassScopeSpecializationPattern(); - + if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { + if (auto *Spec = getClassScopeSpecializationPattern()) + return getDefinitionOrSelf(Spec); + return nullptr; + } + // If this is a generic lambda call operator specialization, its // instantiation pattern is always its primary template's pattern // even if its primary template was instantiated from another @@ -3216,16 +3269,10 @@ FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const { if (isGenericLambdaCallOperatorSpecialization( dyn_cast<CXXMethodDecl>(this))) { - assert(getPrimaryTemplate() && "A generic lambda specialization must be " - "generated from a primary call operator " - "template"); - assert(getPrimaryTemplate()->getTemplatedDecl()->getBody() && - "A generic lambda call operator template must always have a body - " - "even if instantiated from a prototype (i.e. as written) member " - "template"); - return getPrimaryTemplate()->getTemplatedDecl(); + assert(getPrimaryTemplate() && "not a generic lambda call operator?"); + return getDefinitionOrSelf(getPrimaryTemplate()->getTemplatedDecl()); } - + if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) { while (Primary->getInstantiatedFromMemberTemplate()) { // If we have hit a point where the user provided a specialization of @@ -3234,11 +3281,14 @@ FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const { break; Primary = Primary->getInstantiatedFromMemberTemplate(); } - - return Primary->getTemplatedDecl(); + + return getDefinitionOrSelf(Primary->getTemplatedDecl()); } - - return getInstantiatedFromMemberFunction(); + + if (auto *MFD = getInstantiatedFromMemberFunction()) + return getDefinitionOrSelf(MFD); + + return nullptr; } FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { @@ -3744,6 +3794,20 @@ void EnumDecl::completeDefinition(QualType NewType, TagDecl::completeDefinition(); } +bool EnumDecl::isClosed() const { + if (const auto *A = getAttr<EnumExtensibilityAttr>()) + return A->getExtensibility() == EnumExtensibilityAttr::Closed; + return true; +} + +bool EnumDecl::isClosedFlag() const { + return isClosed() && hasAttr<FlagEnumAttr>(); +} + +bool EnumDecl::isClosedNonFlag() const { + return isClosed() && !hasAttr<FlagEnumAttr>(); +} + TemplateSpecializationKind EnumDecl::getTemplateSpecializationKind() const { if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) return MSI->getTemplateSpecializationKind(); @@ -3768,7 +3832,7 @@ EnumDecl *EnumDecl::getTemplateInstantiationPattern() const { EnumDecl *ED = getInstantiatedFromMemberEnum(); while (auto *NewED = ED->getInstantiatedFromMemberEnum()) ED = NewED; - return ED; + return getDefinitionOrSelf(ED); } } @@ -4096,15 +4160,19 @@ void ImplicitParamDecl::anchor() { } ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, - IdentifierInfo *Id, - QualType Type) { - return new (C, DC) ImplicitParamDecl(C, DC, IdLoc, Id, Type); + IdentifierInfo *Id, QualType Type, + ImplicitParamKind ParamKind) { + return new (C, DC) ImplicitParamDecl(C, DC, IdLoc, Id, Type, ParamKind); +} + +ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, QualType Type, + ImplicitParamKind ParamKind) { + return new (C, nullptr) ImplicitParamDecl(C, Type, ParamKind); } ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - return new (C, ID) ImplicitParamDecl(C, nullptr, SourceLocation(), nullptr, - QualType()); + return new (C, ID) ImplicitParamDecl(C, QualType(), ImplicitParamKind::Other); } FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, @@ -4230,6 +4298,30 @@ TagDecl *TypedefNameDecl::getAnonDeclWithTypedefName(bool AnyRedecl) const { return nullptr; } +bool TypedefNameDecl::isTransparentTagSlow() const { + auto determineIsTransparent = [&]() { + if (auto *TT = getUnderlyingType()->getAs<TagType>()) { + if (auto *TD = TT->getDecl()) { + if (TD->getName() != getName()) + return false; + SourceLocation TTLoc = getLocation(); + SourceLocation TDLoc = TD->getLocation(); + if (!TTLoc.isMacroID() || !TDLoc.isMacroID()) + return false; + SourceManager &SM = getASTContext().getSourceManager(); + return SM.getSpellingLoc(TTLoc) == SM.getSpellingLoc(TDLoc); + } + } + return false; + }; + + bool isTransparent = determineIsTransparent(); + CacheIsTransparentTag = 1; + if (isTransparent) + CacheIsTransparentTag |= 0x2; + return isTransparent; +} + TypedefDecl *TypedefDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) TypedefDecl(C, nullptr, SourceLocation(), SourceLocation(), nullptr, nullptr); diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp index 6111aba..cd2c83a 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp @@ -75,7 +75,7 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Ctx, assert(!Parent || &Parent->getParentASTContext() == &Ctx); // With local visibility enabled, we track the owning module even for local // declarations. - if (Ctx.getLangOpts().ModulesLocalVisibility) { + if (Ctx.getLangOpts().trackLocalOwningModule()) { // Ensure required alignment of the resulting object by adding extra // padding at the start if required. size_t ExtraAlign = @@ -83,7 +83,9 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Ctx, char *Buffer = reinterpret_cast<char *>( ::operator new(ExtraAlign + sizeof(Module *) + Size + Extra, Ctx)); Buffer += ExtraAlign; - return new (Buffer) Module*(nullptr) + 1; + auto *ParentModule = + Parent ? cast<Decl>(Parent)->getOwningModule() : nullptr; + return new (Buffer) Module*(ParentModule) + 1; } return ::operator new(Size + Extra, Ctx); } @@ -94,7 +96,7 @@ Module *Decl::getOwningModuleSlow() const { } bool Decl::hasLocalOwningModuleStorage() const { - return getASTContext().getLangOpts().ModulesLocalVisibility; + return getASTContext().getLangOpts().trackLocalOwningModule(); } const char *Decl::getDeclKindName() const { @@ -272,7 +274,19 @@ void Decl::setLexicalDeclContext(DeclContext *DC) { } else { getMultipleDC()->LexicalDC = DC; } - Hidden = cast<Decl>(DC)->Hidden; + + // FIXME: We shouldn't be changing the lexical context of declarations + // imported from AST files. + if (!isFromASTFile()) { + setModuleOwnershipKind(getModuleOwnershipKindForChildOf(DC)); + if (hasOwningModule()) + setLocalOwningModule(cast<Decl>(DC)->getOwningModule()); + } + + assert( + (getModuleOwnershipKind() != ModuleOwnershipKind::VisibleWhenImported || + getOwningModule()) && + "hidden declaration has no owning module"); } void Decl::setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC, @@ -403,6 +417,27 @@ bool Decl::isExported() const { return false; } +ExternalSourceSymbolAttr *Decl::getExternalSourceSymbolAttr() const { + const Decl *Definition = nullptr; + if (auto ID = dyn_cast<ObjCInterfaceDecl>(this)) { + Definition = ID->getDefinition(); + } else if (auto PD = dyn_cast<ObjCProtocolDecl>(this)) { + Definition = PD->getDefinition(); + } else if (auto TD = dyn_cast<TagDecl>(this)) { + Definition = TD->getDefinition(); + } + if (!Definition) + Definition = this; + + if (auto *attr = Definition->getAttr<ExternalSourceSymbolAttr>()) + return attr; + if (auto *dcd = dyn_cast<Decl>(getDeclContext())) { + return dcd->getAttr<ExternalSourceSymbolAttr>(); + } + + return nullptr; +} + bool Decl::hasDefiningAttr() const { return hasAttr<AliasAttr>() || hasAttr<IFuncAttr>(); } @@ -415,6 +450,19 @@ const Attr *Decl::getDefiningAttr() const { return nullptr; } +static StringRef getRealizedPlatform(const AvailabilityAttr *A, + const ASTContext &Context) { + // Check if this is an App Extension "platform", and if so chop off + // the suffix for matching with the actual platform. + StringRef RealizedPlatform = A->getPlatform()->getName(); + if (!Context.getLangOpts().AppExt) + return RealizedPlatform; + size_t suffix = RealizedPlatform.rfind("_app_extension"); + if (suffix != StringRef::npos) + return RealizedPlatform.slice(0, suffix); + return RealizedPlatform; +} + /// \brief Determine the availability of the given declaration based on /// the target platform. /// @@ -434,20 +482,11 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, if (EnclosingVersion.empty()) return AR_Available; - // Check if this is an App Extension "platform", and if so chop off - // the suffix for matching with the actual platform. StringRef ActualPlatform = A->getPlatform()->getName(); - StringRef RealizedPlatform = ActualPlatform; - if (Context.getLangOpts().AppExt) { - size_t suffix = RealizedPlatform.rfind("_app_extension"); - if (suffix != StringRef::npos) - RealizedPlatform = RealizedPlatform.slice(0, suffix); - } - StringRef TargetPlatform = Context.getTargetInfo().getPlatformName(); // Match the platform name. - if (RealizedPlatform != TargetPlatform) + if (getRealizedPlatform(A, Context) != TargetPlatform) return AR_Available; StringRef PrettyPlatformName @@ -567,6 +606,20 @@ AvailabilityResult Decl::getAvailability(std::string *Message, return Result; } +VersionTuple Decl::getVersionIntroduced() const { + const ASTContext &Context = getASTContext(); + StringRef TargetPlatform = Context.getTargetInfo().getPlatformName(); + for (const auto *A : attrs()) { + if (const auto *Availability = dyn_cast<AvailabilityAttr>(A)) { + if (getRealizedPlatform(Availability, Context) != TargetPlatform) + continue; + if (!Availability->getIntroduced().empty()) + return Availability->getIntroduced(); + } + } + return VersionTuple(); +} + bool Decl::canBeWeakImported(bool &IsDefinition) const { IsDefinition = false; @@ -619,6 +672,7 @@ bool Decl::isWeakImported() const { unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { switch (DeclKind) { case Function: + case CXXDeductionGuide: case CXXMethod: case CXXConstructor: case ConstructorUsingShadow: @@ -1300,7 +1354,7 @@ void DeclContext::removeDecl(Decl *D) { // Remove only decls that have a name if (!ND->getDeclName()) return; - auto *DC = this; + auto *DC = D->getDeclContext(); do { StoredDeclsMap *Map = DC->getPrimaryContext()->LookupPtr; if (Map) { diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp index a9db65a..5782b7b 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp @@ -18,6 +18,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ODRHash.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/STLExtras.h" @@ -54,25 +55,30 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) HasOnlyCMembers(true), HasInClassInitializer(false), HasUninitializedReferenceMember(false), HasUninitializedFields(false), HasInheritedConstructor(false), HasInheritedAssignment(false), + NeedOverloadResolutionForCopyConstructor(false), NeedOverloadResolutionForMoveConstructor(false), NeedOverloadResolutionForMoveAssignment(false), NeedOverloadResolutionForDestructor(false), + DefaultedCopyConstructorIsDeleted(false), DefaultedMoveConstructorIsDeleted(false), DefaultedMoveAssignmentIsDeleted(false), DefaultedDestructorIsDeleted(false), HasTrivialSpecialMembers(SMF_All), DeclaredNonTrivialSpecialMembers(0), HasIrrelevantDestructor(true), HasConstexprNonCopyMoveConstructor(false), HasDefaultedDefaultConstructor(false), + CanPassInRegisters(true), DefaultedDefaultConstructorIsConstexpr(true), HasConstexprDefaultConstructor(false), HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false), UserProvidedDefaultConstructor(false), DeclaredSpecialMembers(0), - ImplicitCopyConstructorHasConstParam(true), + ImplicitCopyConstructorCanHaveConstParamForVBase(true), + ImplicitCopyConstructorCanHaveConstParamForNonVBase(true), ImplicitCopyAssignmentHasConstParam(true), HasDeclaredCopyConstructorWithConstParam(false), HasDeclaredCopyAssignmentWithConstParam(false), IsLambda(false), - IsParsingBaseSpecifiers(false), NumBases(0), NumVBases(0), Bases(), - VBases(), Definition(D), FirstFriend() {} + IsParsingBaseSpecifiers(false), HasODRHash(false), ODRHash(0), + NumBases(0), NumVBases(0), Bases(), VBases(), Definition(D), + FirstFriend() {} CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase() const { return Bases.get(Definition->getASTContext().getExternalSource()); @@ -226,7 +232,7 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // 'const B&' or 'const volatile B&' [...] if (CXXRecordDecl *VBaseDecl = VBase.getType()->getAsCXXRecordDecl()) if (!VBaseDecl->hasCopyConstructorWithConstParam()) - data().ImplicitCopyConstructorHasConstParam = false; + data().ImplicitCopyConstructorCanHaveConstParamForVBase = false; // C++1z [dcl.init.agg]p1: // An aggregate is a class with [...] no virtual base classes @@ -263,6 +269,14 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // In the definition of a constexpr constructor [...] // -- the class shall not have any virtual base classes data().DefaultedDefaultConstructorIsConstexpr = false; + + // C++1z [class.copy]p8: + // The implicitly-declared copy constructor for a class X will have + // the form 'X::X(const X&)' if each potentially constructed subobject + // has a copy constructor whose first parameter is of type + // 'const B&' or 'const volatile B&' [...] + if (!BaseClassDecl->hasCopyConstructorWithConstParam()) + data().ImplicitCopyConstructorCanHaveConstParamForVBase = false; } else { // C++ [class.ctor]p5: // A default constructor is trivial [...] if: @@ -305,6 +319,14 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // default constructor is constexpr. if (!BaseClassDecl->hasConstexprDefaultConstructor()) data().DefaultedDefaultConstructorIsConstexpr = false; + + // C++1z [class.copy]p8: + // The implicitly-declared copy constructor for a class X will have + // the form 'X::X(const X&)' if each potentially constructed subobject + // has a copy constructor whose first parameter is of type + // 'const B&' or 'const volatile B&' [...] + if (!BaseClassDecl->hasCopyConstructorWithConstParam()) + data().ImplicitCopyConstructorCanHaveConstParamForNonVBase = false; } // C++ [class.ctor]p3: @@ -324,14 +346,6 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, if (!BaseClassDecl->hasCopyAssignmentWithConstParam()) data().ImplicitCopyAssignmentHasConstParam = false; - // C++11 [class.copy]p8: - // The implicitly-declared copy constructor for a class X will have - // the form 'X::X(const X&)' if each direct [...] base class B of X - // has a copy constructor whose first parameter is of type - // 'const B&' or 'const volatile B&' [...] - if (!BaseClassDecl->hasCopyConstructorWithConstParam()) - data().ImplicitCopyConstructorHasConstParam = false; - // A class has an Objective-C object member if... or any of its bases // has an Objective-C object member. if (BaseClassDecl->hasObjectMember()) @@ -341,8 +355,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, setHasVolatileMember(true); // Keep track of the presence of mutable fields. - if (BaseClassDecl->hasMutableFields()) + if (BaseClassDecl->hasMutableFields()) { data().HasMutableFields = true; + data().NeedOverloadResolutionForCopyConstructor = true; + } if (BaseClassDecl->hasUninitializedReferenceMember()) data().HasUninitializedReferenceMember = true; @@ -371,6 +387,23 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, data().IsParsingBaseSpecifiers = false; } +unsigned CXXRecordDecl::getODRHash() const { + assert(hasDefinition() && "ODRHash only for records with definitions"); + + // Previously calculated hash is stored in DefinitionData. + if (DefinitionData->HasODRHash) + return DefinitionData->ODRHash; + + // Only calculate hash on first call of getODRHash per record. + ODRHash Hash; + Hash.AddCXXRecordDecl(getDefinition()); + DefinitionData->HasODRHash = true; + DefinitionData->ODRHash = Hash.CalculateHash(); + + return DefinitionData->ODRHash; +} + + void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) { // C++11 [class.copy]p11: // A defaulted copy/move constructor for a class X is defined as @@ -378,6 +411,8 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) { // -- a direct or virtual base class B that cannot be copied/moved [...] // -- a non-static data member of class type M (or array thereof) // that cannot be copied or moved [...] + if (!Subobj->hasSimpleCopyConstructor()) + data().NeedOverloadResolutionForCopyConstructor = true; if (!Subobj->hasSimpleMoveConstructor()) data().NeedOverloadResolutionForMoveConstructor = true; @@ -398,6 +433,7 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) { // -- any non-static data member has a type with a destructor // that is deleted or inaccessible from the defaulted [ctor or dtor]. if (!Subobj->hasSimpleDestructor()) { + data().NeedOverloadResolutionForCopyConstructor = true; data().NeedOverloadResolutionForMoveConstructor = true; data().NeedOverloadResolutionForDestructor = true; } @@ -683,8 +719,10 @@ void CXXRecordDecl::addedMember(Decl *D) { data().IsStandardLayout = false; // Keep track of the presence of mutable fields. - if (Field->isMutable()) + if (Field->isMutable()) { data().HasMutableFields = true; + data().NeedOverloadResolutionForCopyConstructor = true; + } // C++11 [class.union]p8, DR1460: // If X is a union, a non-static data member of X that is not an anonymous @@ -702,9 +740,7 @@ void CXXRecordDecl::addedMember(Decl *D) { ASTContext &Context = getASTContext(); QualType T = Context.getBaseElementType(Field->getType()); if (T->isObjCRetainableType() || T.isObjCGCStrong()) { - if (!Context.getLangOpts().ObjCAutoRefCount) { - setHasObjectMember(true); - } else if (T.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) { + if (T.hasNonTrivialObjCLifetime()) { // Objective-C Automatic Reference Counting: // If a class has a non-static data member of Objective-C pointer // type (or array thereof), it is a non-POD type and its @@ -716,6 +752,8 @@ void CXXRecordDecl::addedMember(Decl *D) { Data.PlainOldData = false; Data.HasTrivialSpecialMembers = 0; Data.HasIrrelevantDestructor = false; + } else if (!Context.getLangOpts().ObjCAutoRefCount) { + setHasObjectMember(true); } } else if (!T.isCXX98PODType(Context)) data().PlainOldData = false; @@ -728,6 +766,12 @@ void CXXRecordDecl::addedMember(Decl *D) { // A standard-layout class is a class that: // -- has no non-static data members of type [...] reference, data().IsStandardLayout = false; + + // C++1z [class.copy.ctor]p10: + // A defaulted copy constructor for a class X is defined as deleted if X has: + // -- a non-static data member of rvalue reference type + if (T->isRValueReferenceType()) + data().DefaultedCopyConstructorIsDeleted = true; } if (!Field->hasInClassInitializer() && !Field->isMutable()) { @@ -781,6 +825,10 @@ void CXXRecordDecl::addedMember(Decl *D) { // We may need to perform overload resolution to determine whether a // field can be moved if it's const or volatile qualified. if (T.getCVRQualifiers() & (Qualifiers::Const | Qualifiers::Volatile)) { + // We need to care about 'const' for the copy constructor because an + // implicit copy constructor might be declared with a non-const + // parameter. + data().NeedOverloadResolutionForCopyConstructor = true; data().NeedOverloadResolutionForMoveConstructor = true; data().NeedOverloadResolutionForMoveAssignment = true; } @@ -791,6 +839,8 @@ void CXXRecordDecl::addedMember(Decl *D) { // -- X is a union-like class that has a variant member with a // non-trivial [corresponding special member] if (isUnion()) { + if (FieldRec->hasNonTrivialCopyConstructor()) + data().DefaultedCopyConstructorIsDeleted = true; if (FieldRec->hasNonTrivialMoveConstructor()) data().DefaultedMoveConstructorIsDeleted = true; if (FieldRec->hasNonTrivialMoveAssignment()) @@ -802,6 +852,8 @@ void CXXRecordDecl::addedMember(Decl *D) { // For an anonymous union member, our overload resolution will perform // overload resolution for its members. if (Field->isAnonymousStructOrUnion()) { + data().NeedOverloadResolutionForCopyConstructor |= + FieldRec->data().NeedOverloadResolutionForCopyConstructor; data().NeedOverloadResolutionForMoveConstructor |= FieldRec->data().NeedOverloadResolutionForMoveConstructor; data().NeedOverloadResolutionForMoveAssignment |= @@ -887,8 +939,10 @@ void CXXRecordDecl::addedMember(Decl *D) { } // Keep track of the presence of mutable fields. - if (FieldRec->hasMutableFields()) + if (FieldRec->hasMutableFields()) { data().HasMutableFields = true; + data().NeedOverloadResolutionForCopyConstructor = true; + } // C++11 [class.copy]p13: // If the implicitly-defined constructor would satisfy the @@ -905,12 +959,11 @@ void CXXRecordDecl::addedMember(Decl *D) { // C++11 [class.copy]p8: // The implicitly-declared copy constructor for a class X will have - // the form 'X::X(const X&)' if [...] for all the non-static data - // members of X that are of a class type M (or array thereof), each - // such class type has a copy constructor whose first parameter is - // of type 'const M&' or 'const volatile M&'. + // the form 'X::X(const X&)' if each potentially constructed subobject + // of a class type M (or array thereof) has a copy constructor whose + // first parameter is of type 'const M&' or 'const volatile M&'. if (!FieldRec->hasCopyConstructorWithConstParam()) - data().ImplicitCopyConstructorHasConstParam = false; + data().ImplicitCopyConstructorCanHaveConstParamForNonVBase = false; // C++11 [class.copy]p18: // The implicitly-declared copy assignment oeprator for a class X will @@ -1337,6 +1390,13 @@ CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) { } const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const { + auto GetDefinitionOrSelf = + [](const CXXRecordDecl *D) -> const CXXRecordDecl * { + if (auto *Def = D->getDefinition()) + return Def; + return D; + }; + // If it's a class template specialization, find the template or partial // specialization from which it was instantiated. if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) { @@ -1347,7 +1407,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const { break; CTD = NewCTD; } - return CTD->getTemplatedDecl()->getDefinition(); + return GetDefinitionOrSelf(CTD->getTemplatedDecl()); } if (auto *CTPSD = From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) { @@ -1356,7 +1416,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const { break; CTPSD = NewCTPSD; } - return CTPSD->getDefinition(); + return GetDefinitionOrSelf(CTPSD); } } @@ -1365,7 +1425,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const { const CXXRecordDecl *RD = this; while (auto *NewRD = RD->getInstantiatedFromMemberClass()) RD = NewRD; - return RD->getDefinition(); + return GetDefinitionOrSelf(RD); } } @@ -1383,11 +1443,8 @@ CXXDestructorDecl *CXXRecordDecl::getDestructor() const { Context.getCanonicalType(ClassType)); DeclContext::lookup_result R = lookup(Name); - if (R.empty()) - return nullptr; - CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(R.front()); - return Dtor; + return R.empty() ? nullptr : dyn_cast<CXXDestructorDecl>(R.front()); } bool CXXRecordDecl::isAnyDestructorNoReturn() const { @@ -1398,8 +1455,9 @@ bool CXXRecordDecl::isAnyDestructorNoReturn() const { // Check base classes destructor for noreturn. for (const auto &Base : bases()) - if (Base.getType()->getAsCXXRecordDecl()->isAnyDestructorNoReturn()) - return true; + if (const CXXRecordDecl *RD = Base.getType()->getAsCXXRecordDecl()) + if (RD->isAnyDestructorNoReturn()) + return true; // Check fields for noreturn. for (const auto *Field : fields()) @@ -1418,7 +1476,7 @@ void CXXRecordDecl::completeDefinition() { void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) { RecordDecl::completeDefinition(); - + // If the class may be abstract (but hasn't been marked as such), check for // any pure final overriders. if (mayBeAbstract()) { @@ -1472,6 +1530,23 @@ bool CXXRecordDecl::mayBeAbstract() const { return false; } +void CXXDeductionGuideDecl::anchor() { } + +CXXDeductionGuideDecl *CXXDeductionGuideDecl::Create( + ASTContext &C, DeclContext *DC, SourceLocation StartLoc, bool IsExplicit, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, + SourceLocation EndLocation) { + return new (C, DC) CXXDeductionGuideDecl(C, DC, StartLoc, IsExplicit, + NameInfo, T, TInfo, EndLocation); +} + +CXXDeductionGuideDecl *CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + return new (C, ID) CXXDeductionGuideDecl(C, nullptr, SourceLocation(), false, + DeclarationNameInfo(), QualType(), + nullptr, SourceLocation()); +} + void CXXMethodDecl::anchor() { } bool CXXMethodDecl::isStatic() const { @@ -1556,6 +1631,84 @@ CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) { SC_None, false, false, SourceLocation()); } +CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base, + bool IsAppleKext) { + assert(isVirtual() && "this method is expected to be virtual"); + + // When building with -fapple-kext, all calls must go through the vtable since + // the kernel linker can do runtime patching of vtables. + if (IsAppleKext) + return nullptr; + + // If the member function is marked 'final', we know that it can't be + // overridden and can therefore devirtualize it unless it's pure virtual. + if (hasAttr<FinalAttr>()) + return isPure() ? nullptr : this; + + // If Base is unknown, we cannot devirtualize. + if (!Base) + return nullptr; + + // If the base expression (after skipping derived-to-base conversions) is a + // class prvalue, then we can devirtualize. + Base = Base->getBestDynamicClassTypeExpr(); + if (Base->isRValue() && Base->getType()->isRecordType()) + return this; + + // If we don't even know what we would call, we can't devirtualize. + const CXXRecordDecl *BestDynamicDecl = Base->getBestDynamicClassType(); + if (!BestDynamicDecl) + return nullptr; + + // There may be a method corresponding to MD in a derived class. + CXXMethodDecl *DevirtualizedMethod = + getCorrespondingMethodInClass(BestDynamicDecl); + + // If that method is pure virtual, we can't devirtualize. If this code is + // reached, the result would be UB, not a direct call to the derived class + // function, and we can't assume the derived class function is defined. + if (DevirtualizedMethod->isPure()) + return nullptr; + + // If that method is marked final, we can devirtualize it. + if (DevirtualizedMethod->hasAttr<FinalAttr>()) + return DevirtualizedMethod; + + // Similarly, if the class itself is marked 'final' it can't be overridden + // and we can therefore devirtualize the member function call. + if (BestDynamicDecl->hasAttr<FinalAttr>()) + return DevirtualizedMethod; + + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) { + if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) + if (VD->getType()->isRecordType()) + // This is a record decl. We know the type and can devirtualize it. + return DevirtualizedMethod; + + return nullptr; + } + + // We can devirtualize calls on an object accessed by a class member access + // expression, since by C++11 [basic.life]p6 we know that it can't refer to + // a derived class object constructed in the same location. + if (const MemberExpr *ME = dyn_cast<MemberExpr>(Base)) + if (const ValueDecl *VD = dyn_cast<ValueDecl>(ME->getMemberDecl())) + return VD->getType()->isRecordType() ? DevirtualizedMethod : nullptr; + + // Likewise for calls on an object accessed by a (non-reference) pointer to + // member access. + if (auto *BO = dyn_cast<BinaryOperator>(Base)) { + if (BO->isPtrMemOp()) { + auto *MPT = BO->getRHS()->getType()->castAs<MemberPointerType>(); + if (MPT->getPointeeType()->isRecordType()) + return DevirtualizedMethod; + } + } + + // We can't devirtualize the call. + return nullptr; +} + bool CXXMethodDecl::isUsualDeallocationFunction() const { if (getOverloadedOperator() != OO_Delete && getOverloadedOperator() != OO_Array_Delete) @@ -1710,9 +1863,10 @@ bool CXXMethodDecl::hasInlineBody() const { const FunctionDecl *CheckFn = getTemplateInstantiationPattern(); if (!CheckFn) CheckFn = this; - + const FunctionDecl *fn; - return CheckFn->hasBody(fn) && !fn->isOutOfLine(); + return CheckFn->isDefined(fn) && !fn->isOutOfLine() && + (fn->doesThisDeclarationHaveABody() || fn->willHaveBody()); } bool CXXMethodDecl::isLambdaStaticInvoker() const { diff --git a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp index 60d05f6..d8bdb63 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp @@ -162,10 +162,10 @@ ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC, return nullptr; } - // If context is class, then lookup property in its extensions. + // If context is class, then lookup property in its visible extensions. // This comes before property is looked up in primary class. if (auto *IDecl = dyn_cast<ObjCInterfaceDecl>(DC)) { - for (const auto *Ext : IDecl->known_extensions()) + for (const auto *Ext : IDecl->visible_extensions()) if (ObjCPropertyDecl *PD = ObjCPropertyDecl::findPropertyDecl(Ext, propertyID, queryKind)) @@ -539,9 +539,18 @@ void ObjCInterfaceDecl::getDesignatedInitializers( bool ObjCInterfaceDecl::isDesignatedInitializer(Selector Sel, const ObjCMethodDecl **InitMethod) const { + bool HasCompleteDef = isThisDeclarationADefinition(); + // During deserialization the data record for the ObjCInterfaceDecl could + // be made invariant by reusing the canonical decl. Take this into account + // when checking for the complete definition. + if (!HasCompleteDef && getCanonicalDecl()->hasDefinition() && + getCanonicalDecl()->getDefinition() == getDefinition()) + HasCompleteDef = true; + // Check for a complete definition and recover if not so. - if (!isThisDeclarationADefinition()) + if (!HasCompleteDef) return false; + if (data().ExternallyCompleted) LoadExternalDefinition(); @@ -1061,20 +1070,20 @@ void ObjCMethodDecl::createImplicitParams(ASTContext &Context, bool selfIsPseudoStrong, selfIsConsumed; QualType selfTy = getSelfType(Context, OID, selfIsPseudoStrong, selfIsConsumed); - ImplicitParamDecl *self - = ImplicitParamDecl::Create(Context, this, SourceLocation(), - &Context.Idents.get("self"), selfTy); - setSelfDecl(self); + auto *Self = ImplicitParamDecl::Create(Context, this, SourceLocation(), + &Context.Idents.get("self"), selfTy, + ImplicitParamDecl::ObjCSelf); + setSelfDecl(Self); if (selfIsConsumed) - self->addAttr(NSConsumedAttr::CreateImplicit(Context)); + Self->addAttr(NSConsumedAttr::CreateImplicit(Context)); if (selfIsPseudoStrong) - self->setARCPseudoStrong(true); + Self->setARCPseudoStrong(true); - setCmdDecl(ImplicitParamDecl::Create(Context, this, SourceLocation(), - &Context.Idents.get("_cmd"), - Context.getObjCSelType())); + setCmdDecl(ImplicitParamDecl::Create( + Context, this, SourceLocation(), &Context.Idents.get("_cmd"), + Context.getObjCSelType(), ImplicitParamDecl::ObjCCmd)); } ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() { @@ -1880,25 +1889,23 @@ void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM, } } - void ObjCProtocolDecl::collectInheritedProtocolProperties( - const ObjCPropertyDecl *Property, - ProtocolPropertyMap &PM) const { + const ObjCPropertyDecl *Property, ProtocolPropertySet &PS, + PropertyDeclOrder &PO) const { if (const ObjCProtocolDecl *PDecl = getDefinition()) { - bool MatchFound = false; + if (!PS.insert(PDecl).second) + return; for (auto *Prop : PDecl->properties()) { if (Prop == Property) continue; if (Prop->getIdentifier() == Property->getIdentifier()) { - PM[PDecl] = Prop; - MatchFound = true; - break; + PO.push_back(Prop); + return; } } // Scan through protocol's protocols which did not have a matching property. - if (!MatchFound) - for (const auto *PI : PDecl->protocols()) - PI->collectInheritedProtocolProperties(Property, PM); + for (const auto *PI : PDecl->protocols()) + PI->collectInheritedProtocolProperties(Property, PS, PO); } } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp index b8ebe1c..6eeba88 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp @@ -464,6 +464,7 @@ void DeclPrinter::VisitRecordDecl(RecordDecl *D) { void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) { Out << *D; + prettyPrintAttributes(D); if (Expr *Init = D->getInitExpr()) { Out << " = "; Init->printPretty(Out, nullptr, Policy, Indentation); @@ -477,9 +478,15 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (D->isFunctionTemplateSpecialization()) Out << "template<> "; + else if (!D->getDescribedFunctionTemplate()) { + for (unsigned I = 0, NumTemplateParams = D->getNumTemplateParameterLists(); + I < NumTemplateParams; ++I) + printTemplateParameters(D->getTemplateParameterList(I)); + } CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D); CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D); + CXXDeductionGuideDecl *GuideDecl = dyn_cast<CXXDeductionGuideDecl>(D); if (!Policy.SuppressSpecifiers) { switch (D->getStorageClass()) { case SC_None: break; @@ -495,13 +502,23 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (D->isModulePrivate()) Out << "__module_private__ "; if (D->isConstexpr() && !D->isExplicitlyDefaulted()) Out << "constexpr "; if ((CDecl && CDecl->isExplicitSpecified()) || - (ConversionDecl && ConversionDecl->isExplicit())) + (ConversionDecl && ConversionDecl->isExplicitSpecified()) || + (GuideDecl && GuideDecl->isExplicitSpecified())) Out << "explicit "; } PrintingPolicy SubPolicy(Policy); SubPolicy.SuppressSpecifiers = false; - std::string Proto = D->getNameInfo().getAsString(); + std::string Proto; + if (!Policy.SuppressScope) { + if (const NestedNameSpecifier *NS = D->getQualifier()) { + llvm::raw_string_ostream OS(Proto); + NS->print(OS, Policy); + } + } + Proto += D->getNameInfo().getAsString(); + if (GuideDecl) + Proto = GuideDecl->getDeducedTemplate()->getDeclName().getAsString(); if (const TemplateArgumentList *TArgs = D->getTemplateSpecializationArgs()) { llvm::raw_string_ostream POut(Proto); DeclPrinter TArgPrinter(POut, SubPolicy, Indentation); @@ -651,7 +668,9 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { } } else if (!ConversionDecl && !isa<CXXDestructorDecl>(D)) { if (FT && FT->hasTrailingReturn()) { - Out << "auto " << Proto << " -> "; + if (!GuideDecl) + Out << "auto "; + Out << Proto << " -> "; Proto.clear(); } AFT->getReturnType().print(Out, Policy, Proto); @@ -1041,9 +1060,18 @@ void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) { void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { prettyPrintPragmas(D->getTemplatedDecl()); + // Print any leading template parameter lists. + if (const FunctionDecl *FD = D->getTemplatedDecl()) { + for (unsigned I = 0, NumTemplateParams = FD->getNumTemplateParameterLists(); + I < NumTemplateParams; ++I) + printTemplateParameters(FD->getTemplateParameterList(I)); + } VisitRedeclarableTemplateDecl(D); - if (PrintInstantiation) { + // Never print "instantiations" for deduction guides (they don't really + // have them). + if (PrintInstantiation && + !isa<CXXDeductionGuideDecl>(D->getTemplatedDecl())) { FunctionDecl *PrevDecl = D->getTemplatedDecl(); const FunctionDecl *Def; if (PrevDecl->isDefined(Def) && Def != PrevDecl) @@ -1161,7 +1189,9 @@ void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { for (const auto *PI : OMD->parameters()) { // FIXME: selector is missing here! pos = name.find_first_of(':', lastPos); - Out << " " << name.substr(lastPos, pos - lastPos) << ':'; + if (lastPos != 0) + Out << " "; + Out << name.substr(lastPos, pos - lastPos) << ':'; PrintObjCMethodType(OMD->getASTContext(), PI->getObjCDeclQualifier(), PI->getType()); @@ -1170,7 +1200,7 @@ void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { } if (OMD->param_begin() == OMD->param_end()) - Out << " " << name; + Out << name; if (OMD->isVariadic()) Out << ", ..."; diff --git a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp index a5fbb0a..00a6739 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp @@ -208,10 +208,6 @@ void RedeclarableTemplateDecl::addSpecializationImpl( // FunctionTemplateDecl Implementation //===----------------------------------------------------------------------===// -void FunctionTemplateDecl::DeallocateCommon(void *Ptr) { - static_cast<Common *>(Ptr)->~Common(); -} - FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -231,7 +227,7 @@ FunctionTemplateDecl *FunctionTemplateDecl::CreateDeserialized(ASTContext &C, RedeclarableTemplateDecl::CommonBase * FunctionTemplateDecl::newCommon(ASTContext &C) const { Common *CommonPtr = new (C) Common; - C.AddDeallocation(DeallocateCommon, CommonPtr); + C.addDestruction(CommonPtr); return CommonPtr; } @@ -288,19 +284,23 @@ ArrayRef<TemplateArgument> FunctionTemplateDecl::getInjectedTemplateArgs() { // ClassTemplateDecl Implementation //===----------------------------------------------------------------------===// -void ClassTemplateDecl::DeallocateCommon(void *Ptr) { - static_cast<Common *>(Ptr)->~Common(); -} - ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, - NamedDecl *Decl) { + NamedDecl *Decl, + Expr *AssociatedConstraints) { AdoptTemplateParameterList(Params, cast<DeclContext>(Decl)); - ClassTemplateDecl *New = new (C, DC) ClassTemplateDecl(C, DC, L, Name, - Params, Decl); + + if (!AssociatedConstraints) { + return new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl); + } + + ConstrainedTemplateDeclInfo *const CTDI = new (C) ConstrainedTemplateDeclInfo; + ClassTemplateDecl *const New = + new (C, DC) ClassTemplateDecl(CTDI, C, DC, L, Name, Params, Decl); + New->setAssociatedConstraints(AssociatedConstraints); return New; } @@ -340,7 +340,7 @@ ClassTemplateDecl::getPartialSpecializations() { RedeclarableTemplateDecl::CommonBase * ClassTemplateDecl::newCommon(ASTContext &C) const { Common *CommonPtr = new (C) Common; - C.AddDeallocation(DeallocateCommon, CommonPtr); + C.addDestruction(CommonPtr); return CommonPtr; } @@ -880,13 +880,10 @@ TypeAliasTemplateDecl *TypeAliasTemplateDecl::CreateDeserialized(ASTContext &C, DeclarationName(), nullptr, nullptr); } -void TypeAliasTemplateDecl::DeallocateCommon(void *Ptr) { - static_cast<Common *>(Ptr)->~Common(); -} RedeclarableTemplateDecl::CommonBase * TypeAliasTemplateDecl::newCommon(ASTContext &C) const { Common *CommonPtr = new (C) Common; - C.AddDeallocation(DeallocateCommon, CommonPtr); + C.addDestruction(CommonPtr); return CommonPtr; } @@ -907,10 +904,6 @@ ClassScopeFunctionSpecializationDecl::CreateDeserialized(ASTContext &C, // VarTemplateDecl Implementation //===----------------------------------------------------------------------===// -void VarTemplateDecl::DeallocateCommon(void *Ptr) { - static_cast<Common *>(Ptr)->~Common(); -} - VarTemplateDecl *VarTemplateDecl::getDefinition() { VarTemplateDecl *CurD = this; while (CurD) { @@ -966,7 +959,7 @@ VarTemplateDecl::getPartialSpecializations() { RedeclarableTemplateDecl::CommonBase * VarTemplateDecl::newCommon(ASTContext &C) const { Common *CommonPtr = new (C) Common; - C.AddDeallocation(DeallocateCommon, CommonPtr); + C.addDestruction(CommonPtr); return CommonPtr; } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp index 52791e5..1f8e26d 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp @@ -14,6 +14,7 @@ #include "clang/AST/DeclarationName.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeOrdering.h" @@ -43,6 +44,22 @@ public: } }; +/// Contains extra information for the name of a C++ deduction guide. +class CXXDeductionGuideNameExtra : public DeclarationNameExtra, + public llvm::FoldingSetNode { +public: + /// The template named by the deduction guide. + TemplateDecl *Template; + + /// FETokenInfo - Extra information associated with this operator + /// name that can be used by the front end. + void *FETokenInfo; + + void Profile(llvm::FoldingSetNodeID &ID) { + ID.AddPointer(Template); + } +}; + /// CXXOperatorIdName - Contains extra information for the name of an /// overloaded operator in C++, such as "operator+. class CXXOperatorIdName : public DeclarationNameExtra { @@ -122,7 +139,13 @@ int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) { if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType())) return 1; return 0; - + + case DeclarationName::CXXDeductionGuideName: + // We never want to compare deduction guide names for templates from + // different scopes, so just compare the template-name. + return compare(LHS.getCXXDeductionGuideTemplate()->getDeclName(), + RHS.getCXXDeductionGuideTemplate()->getDeclName()); + case DeclarationName::CXXOperatorName: return compareInt(LHS.getCXXOverloadedOperator(), RHS.getCXXOverloadedOperator()); @@ -179,6 +202,12 @@ void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) { return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy); } + case DeclarationName::CXXDeductionGuideName: + OS << "<deduction guide for "; + getCXXDeductionGuideTemplate()->getDeclName().print(OS, Policy); + OS << '>'; + return; + case DeclarationName::CXXOperatorName: { static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = { nullptr, @@ -243,6 +272,9 @@ DeclarationName::NameKind DeclarationName::getNameKind() const { case DeclarationNameExtra::CXXDestructor: return CXXDestructorName; + case DeclarationNameExtra::CXXDeductionGuide: + return CXXDeductionGuideName; + case DeclarationNameExtra::CXXConversionFunction: return CXXConversionFunctionName; @@ -268,7 +300,15 @@ DeclarationName::NameKind DeclarationName::getNameKind() const { bool DeclarationName::isDependentName() const { QualType T = getCXXNameType(); - return !T.isNull() && T->isDependentType(); + if (!T.isNull() && T->isDependentType()) + return true; + + // A class-scope deduction guide in a dependent context has a dependent name. + auto *TD = getCXXDeductionGuideTemplate(); + if (TD && TD->getDeclContext()->isDependentContext()) + return true; + + return false; } std::string DeclarationName::getAsString() const { @@ -285,6 +325,12 @@ QualType DeclarationName::getCXXNameType() const { return QualType(); } +TemplateDecl *DeclarationName::getCXXDeductionGuideTemplate() const { + if (auto *Guide = getAsCXXDeductionGuideNameExtra()) + return Guide->Template; + return nullptr; +} + OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const { if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) { unsigned value @@ -312,6 +358,9 @@ void *DeclarationName::getFETokenInfoAsVoidSlow() const { case CXXConversionFunctionName: return getAsCXXSpecialName()->FETokenInfo; + case CXXDeductionGuideName: + return getAsCXXDeductionGuideNameExtra()->FETokenInfo; + case CXXOperatorName: return getAsCXXOperatorIdName()->FETokenInfo; @@ -335,6 +384,10 @@ void DeclarationName::setFETokenInfo(void *T) { getAsCXXSpecialName()->FETokenInfo = T; break; + case CXXDeductionGuideName: + getAsCXXDeductionGuideNameExtra()->FETokenInfo = T; + break; + case CXXOperatorName: getAsCXXOperatorIdName()->FETokenInfo = T; break; @@ -366,6 +419,7 @@ LLVM_DUMP_METHOD void DeclarationName::dump() const { DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) { CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>; CXXLiteralOperatorNames = new llvm::FoldingSet<CXXLiteralOperatorIdName>; + CXXDeductionGuideNames = new llvm::FoldingSet<CXXDeductionGuideNameExtra>; // Initialize the overloaded operator names. CXXOperatorNames = new (Ctx) CXXOperatorIdName[NUM_OVERLOADED_OPERATORS]; @@ -377,14 +431,18 @@ DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) { } DeclarationNameTable::~DeclarationNameTable() { - llvm::FoldingSet<CXXSpecialName> *SpecialNames = - static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl); - llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames - = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*> - (CXXLiteralOperatorNames); + auto *SpecialNames = + static_cast<llvm::FoldingSet<CXXSpecialName> *>(CXXSpecialNamesImpl); + auto *LiteralNames = + static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName> *>( + CXXLiteralOperatorNames); + auto *DeductionGuideNames = + static_cast<llvm::FoldingSet<CXXDeductionGuideNameExtra> *>( + CXXDeductionGuideNames); delete SpecialNames; delete LiteralNames; + delete DeductionGuideNames; } DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) { @@ -398,6 +456,30 @@ DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) { } DeclarationName +DeclarationNameTable::getCXXDeductionGuideName(TemplateDecl *Template) { + Template = cast<TemplateDecl>(Template->getCanonicalDecl()); + + auto *DeductionGuideNames = + static_cast<llvm::FoldingSet<CXXDeductionGuideNameExtra> *>( + CXXDeductionGuideNames); + + llvm::FoldingSetNodeID ID; + ID.AddPointer(Template); + + void *InsertPos = nullptr; + if (auto *Name = DeductionGuideNames->FindNodeOrInsertPos(ID, InsertPos)) + return DeclarationName(Name); + + auto *Name = new (Ctx) CXXDeductionGuideNameExtra; + Name->ExtraKindOrNumArgs = DeclarationNameExtra::CXXDeductionGuide; + Name->Template = Template; + Name->FETokenInfo = nullptr; + + DeductionGuideNames->InsertNode(Name, InsertPos); + return DeclarationName(Name); +} + +DeclarationName DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty) { return getCXXSpecialName(DeclarationName::CXXConversionFunctionName, Ty); } @@ -477,6 +559,7 @@ DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) { DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) { switch (Name.getNameKind()) { case DeclarationName::Identifier: + case DeclarationName::CXXDeductionGuideName: break; case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: @@ -509,6 +592,7 @@ bool DeclarationNameInfo::containsUnexpandedParameterPack() const { case DeclarationName::CXXOperatorName: case DeclarationName::CXXLiteralOperatorName: case DeclarationName::CXXUsingDirective: + case DeclarationName::CXXDeductionGuideName: return false; case DeclarationName::CXXConstructorName: @@ -531,6 +615,7 @@ bool DeclarationNameInfo::isInstantiationDependent() const { case DeclarationName::CXXOperatorName: case DeclarationName::CXXLiteralOperatorName: case DeclarationName::CXXUsingDirective: + case DeclarationName::CXXDeductionGuideName: return false; case DeclarationName::CXXConstructorName: @@ -560,6 +645,7 @@ void DeclarationNameInfo::printName(raw_ostream &OS) const { case DeclarationName::CXXOperatorName: case DeclarationName::CXXLiteralOperatorName: case DeclarationName::CXXUsingDirective: + case DeclarationName::CXXDeductionGuideName: OS << Name; return; @@ -574,7 +660,9 @@ void DeclarationNameInfo::printName(raw_ostream &OS) const { LangOptions LO; LO.CPlusPlus = true; LO.Bool = true; - OS << TInfo->getType().getAsString(PrintingPolicy(LO)); + PrintingPolicy PP(LO); + PP.SuppressScope = true; + OS << TInfo->getType().getAsString(PP); } else OS << Name; return; @@ -585,6 +673,7 @@ void DeclarationNameInfo::printName(raw_ostream &OS) const { SourceLocation DeclarationNameInfo::getEndLoc() const { switch (Name.getNameKind()) { case DeclarationName::Identifier: + case DeclarationName::CXXDeductionGuideName: return NameLoc; case DeclarationName::CXXOperatorName: { diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp index 14f31d0..afc7fa8 100644 --- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp @@ -987,7 +987,7 @@ void StringLiteral::outputString(raw_ostream &OS) const { void StringLiteral::setString(const ASTContext &C, StringRef Str, StringKind Kind, bool IsPascal) { //FIXME: we assume that the string data comes from a target that uses the same - // code unit size and endianess for the type of string. + // code unit size and endianness for the type of string. this->Kind = Kind; this->IsPascal = IsPascal; @@ -1571,10 +1571,12 @@ bool CastExpr::CastConsistency() const { goto CheckNoBasePath; case CK_AddressSpaceConversion: - assert(getType()->isPointerType()); - assert(getSubExpr()->getType()->isPointerType()); + assert(getType()->isPointerType() || getType()->isBlockPointerType()); + assert(getSubExpr()->getType()->isPointerType() || + getSubExpr()->getType()->isBlockPointerType()); assert(getType()->getPointeeType().getAddressSpace() != getSubExpr()->getType()->getPointeeType().getAddressSpace()); + LLVM_FALLTHROUGH; // These should not have an inheritance path. case CK_Dynamic: case CK_ToUnion: @@ -1639,25 +1641,32 @@ const char *CastExpr::getCastKindName() const { llvm_unreachable("Unhandled cast kind!"); } +namespace { + Expr *skipImplicitTemporary(Expr *expr) { + // Skip through reference binding to temporary. + if (MaterializeTemporaryExpr *Materialize + = dyn_cast<MaterializeTemporaryExpr>(expr)) + expr = Materialize->GetTemporaryExpr(); + + // Skip any temporary bindings; they're implicit. + if (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(expr)) + expr = Binder->getSubExpr(); + + return expr; + } +} + Expr *CastExpr::getSubExprAsWritten() { Expr *SubExpr = nullptr; CastExpr *E = this; do { - SubExpr = E->getSubExpr(); + SubExpr = skipImplicitTemporary(E->getSubExpr()); - // Skip through reference binding to temporary. - if (MaterializeTemporaryExpr *Materialize - = dyn_cast<MaterializeTemporaryExpr>(SubExpr)) - SubExpr = Materialize->GetTemporaryExpr(); - - // Skip any temporary bindings; they're implicit. - if (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(SubExpr)) - SubExpr = Binder->getSubExpr(); - // Conversions by constructor and conversion functions have a // subexpression describing the call; strip it off. if (E->getCastKind() == CK_ConstructorConversion) - SubExpr = cast<CXXConstructExpr>(SubExpr)->getArg(0); + SubExpr = + skipImplicitTemporary(cast<CXXConstructExpr>(SubExpr)->getArg(0)); else if (E->getCastKind() == CK_UserDefinedConversion) { assert((isa<CXXMemberCallExpr>(SubExpr) || isa<BlockExpr>(SubExpr)) && @@ -1881,6 +1890,11 @@ bool InitListExpr::isTransparent() const { if (getNumInits() != 1 || !getInit(0)) return false; + // Don't confuse aggregate initialization of a struct X { X &x; }; with a + // transparent struct copy. + if (!getInit(0)->isRValue() && getType()->isRecordType()) + return false; + return getType().getCanonicalType() == getInit(0)->getType().getCanonicalType(); } @@ -2096,6 +2110,7 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, } // Fallthrough for generic call handling. + LLVM_FALLTHROUGH; } case CallExprClass: case CXXMemberCallExprClass: @@ -2952,6 +2967,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case CXXNewExprClass: case CXXDeleteExprClass: case CoawaitExprClass: + case DependentCoawaitExprClass: case CoyieldExprClass: // These always have a side-effect. return true; @@ -3880,16 +3896,22 @@ PseudoObjectExpr::PseudoObjectExpr(QualType type, ExprValueKind VK, // UnaryExprOrTypeTraitExpr Stmt::child_range UnaryExprOrTypeTraitExpr::children() { + const_child_range CCR = + const_cast<const UnaryExprOrTypeTraitExpr *>(this)->children(); + return child_range(cast_away_const(CCR.begin()), cast_away_const(CCR.end())); +} + +Stmt::const_child_range UnaryExprOrTypeTraitExpr::children() const { // If this is of a type and the type is a VLA type (and not a typedef), the // size expression of the VLA needs to be treated as an executable expression. // Why isn't this weirdness documented better in StmtIterator? if (isArgumentType()) { - if (const VariableArrayType* T = dyn_cast<VariableArrayType>( - getArgumentType().getTypePtr())) - return child_range(child_iterator(T), child_iterator()); - return child_range(child_iterator(), child_iterator()); + if (const VariableArrayType *T = + dyn_cast<VariableArrayType>(getArgumentType().getTypePtr())) + return const_child_range(const_child_iterator(T), const_child_iterator()); + return const_child_range(const_child_iterator(), const_child_iterator()); } - return child_range(&Argument.Ex, &Argument.Ex + 1); + return const_child_range(&Argument.Ex, &Argument.Ex + 1); } AtomicExpr::AtomicExpr(SourceLocation BLoc, ArrayRef<Expr*> args, diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp index ad510e0..fe45b5e 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp @@ -734,23 +734,23 @@ CXXBindTemporaryExpr *CXXBindTemporaryExpr::Create(const ASTContext &C, CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(const ASTContext &C, CXXConstructorDecl *Cons, - TypeSourceInfo *Type, + QualType Type, + TypeSourceInfo *TSI, ArrayRef<Expr*> Args, SourceRange ParenOrBraceRange, bool HadMultipleCandidates, bool ListInitialization, bool StdInitListInitialization, bool ZeroInitialization) - : CXXConstructExpr(C, CXXTemporaryObjectExprClass, - Type->getType().getNonReferenceType(), - Type->getTypeLoc().getBeginLoc(), + : CXXConstructExpr(C, CXXTemporaryObjectExprClass, Type, + TSI->getTypeLoc().getBeginLoc(), Cons, false, Args, HadMultipleCandidates, ListInitialization, StdInitListInitialization, ZeroInitialization, CXXConstructExpr::CK_Complete, ParenOrBraceRange), - Type(Type) { + Type(TSI) { } SourceLocation CXXTemporaryObjectExpr::getLocStart() const { @@ -1052,7 +1052,9 @@ CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type, :Type->getType()->isRValueReferenceType()? VK_XValue :VK_RValue), OK_Ordinary, - Type->getType()->isDependentType(), true, true, + Type->getType()->isDependentType() || + Type->getType()->getContainedDeducedType(), + true, true, Type->getType()->containsUnexpandedParameterPack()), Type(Type), LParenLoc(LParenLoc), diff --git a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp index adb74b8..d149bdd 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp @@ -129,6 +129,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::UnresolvedLookupExprClass: case Expr::UnresolvedMemberExprClass: case Expr::TypoExprClass: + case Expr::DependentCoawaitExprClass: case Expr::CXXDependentScopeMemberExprClass: case Expr::DependentScopeDeclRefExprClass: // ObjC instance variables are lvalues @@ -189,7 +190,6 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::ArrayInitIndexExprClass: case Expr::NoInitExprClass: case Expr::DesignatedInitUpdateExprClass: - case Expr::CoyieldExprClass: return Cl::CL_PRValue; // Next come the complicated cases. @@ -413,7 +413,8 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { return ClassifyInternal(Ctx, cast<InitListExpr>(E)->getInit(0)); case Expr::CoawaitExprClass: - return ClassifyInternal(Ctx, cast<CoawaitExpr>(E)->getResumeExpr()); + case Expr::CoyieldExprClass: + return ClassifyInternal(Ctx, cast<CoroutineSuspendExpr>(E)->getResumeExpr()); } llvm_unreachable("unhandled expression kind in classification"); @@ -626,7 +627,8 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, // Const stuff is obviously not modifiable. if (CT.isConstQualified()) return Cl::CM_ConstQualified; - if (CT.getQualifiers().getAddressSpace() == LangAS::opencl_constant) + if (Ctx.getLangOpts().OpenCL && + CT.getQualifiers().getAddressSpace() == LangAS::opencl_constant) return Cl::CM_ConstAddrSpace; // Arrays are not modifiable, only their elements are. diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp index 2c0fce9..df02e10 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp @@ -350,36 +350,49 @@ namespace { MostDerivedArraySize = 2; MostDerivedPathLength = Entries.size(); } - void diagnosePointerArithmetic(EvalInfo &Info, const Expr *E, uint64_t N); + void diagnosePointerArithmetic(EvalInfo &Info, const Expr *E, + const APSInt &N); /// Add N to the address of this subobject. - void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) { - if (Invalid) return; + void adjustIndex(EvalInfo &Info, const Expr *E, APSInt N) { + if (Invalid || !N) return; + uint64_t TruncatedN = N.extOrTrunc(64).getZExtValue(); 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 > getMostDerivedArraySize()) { - diagnosePointerArithmetic(Info, E, Entries.back().ArrayIndex); - setInvalid(); - } + // FIXME: Should we reject if this overflows, at least? + Entries.back().ArrayIndex += TruncatedN; return; } + // [expr.add]p4: For the purposes of these operators, a pointer to a // nonarray object behaves the same as a pointer to the first element of // an array of length one with the type of the object as its element type. - if (IsOnePastTheEnd && N == (uint64_t)-1) - IsOnePastTheEnd = false; - else if (!IsOnePastTheEnd && N == 1) - IsOnePastTheEnd = true; - else if (N != 0) { - diagnosePointerArithmetic(Info, E, uint64_t(IsOnePastTheEnd) + N); + bool IsArray = MostDerivedPathLength == Entries.size() && + MostDerivedIsArrayElement; + uint64_t ArrayIndex = + IsArray ? Entries.back().ArrayIndex : (uint64_t)IsOnePastTheEnd; + uint64_t ArraySize = + IsArray ? getMostDerivedArraySize() : (uint64_t)1; + + if (N < -(int64_t)ArrayIndex || N > ArraySize - ArrayIndex) { + // Calculate the actual index in a wide enough type, so we can include + // it in the note. + N = N.extend(std::max<unsigned>(N.getBitWidth() + 1, 65)); + (llvm::APInt&)N += ArrayIndex; + assert(N.ugt(ArraySize) && "bounds check failed for in-bounds index"); + diagnosePointerArithmetic(Info, E, N); setInvalid(); + return; } + + ArrayIndex += TruncatedN; + assert(ArrayIndex <= ArraySize && + "bounds check succeeded for out-of-bounds index"); + + if (IsArray) + Entries.back().ArrayIndex = ArrayIndex; + else + IsOnePastTheEnd = (ArrayIndex != 0); } }; @@ -413,6 +426,17 @@ namespace { /// Index - The call index of this call. unsigned Index; + // FIXME: Adding this to every 'CallStackFrame' may have a nontrivial impact + // on the overall stack usage of deeply-recursing constexpr evaluataions. + // (We should cache this map rather than recomputing it repeatedly.) + // But let's try this and see how it goes; we can look into caching the map + // as a later change. + + /// LambdaCaptureFields - Mapping from captured variables/this to + /// corresponding data members in the closure class. + llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; + FieldDecl *LambdaThisCaptureField; + CallStackFrame(EvalInfo &Info, SourceLocation CallLoc, const FunctionDecl *Callee, const LValue *This, APValue *Arguments); @@ -712,6 +736,7 @@ namespace { if (!HasFoldFailureDiagnostic) break; // We've already failed to fold something. Keep that diagnostic. + LLVM_FALLTHROUGH; case EM_ConstantExpression: case EM_PotentialConstantExpression: case EM_ConstantExpressionUnevaluated: @@ -1048,16 +1073,17 @@ bool SubobjectDesignator::checkSubobject(EvalInfo &Info, const Expr *E, } void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info, - const Expr *E, uint64_t N) { + const Expr *E, + const APSInt &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 + << N << /*array*/ 0 << static_cast<unsigned>(getMostDerivedArraySize()); else Info.CCEDiag(E, diag::note_constexpr_array_index) - << static_cast<int>(N) << /*non-array*/ 1; + << N << /*non-array*/ 1; setInvalid(); } @@ -1205,8 +1231,7 @@ namespace { IsNullPtr = V.isNullPointer(); } - void set(APValue::LValueBase B, unsigned I = 0, bool BInvalid = false, - bool IsNullPtr_ = false, uint64_t Offset_ = 0) { + void set(APValue::LValueBase B, unsigned I = 0, bool BInvalid = false) { #ifndef NDEBUG // We only allow a few types of invalid bases. Enforce that here. if (BInvalid) { @@ -1217,11 +1242,20 @@ namespace { #endif Base = B; - Offset = CharUnits::fromQuantity(Offset_); + Offset = CharUnits::fromQuantity(0); InvalidBase = BInvalid; CallIndex = I; Designator = SubobjectDesignator(getType(B)); - IsNullPtr = IsNullPtr_; + IsNullPtr = false; + } + + void setNull(QualType PointerTy, uint64_t TargetVal) { + Base = (Expr *)nullptr; + Offset = CharUnits::fromQuantity(TargetVal); + InvalidBase = false; + CallIndex = 0; + Designator = SubobjectDesignator(PointerTy->getPointeeType()); + IsNullPtr = true; } void setInvalid(APValue::LValueBase B, unsigned I = 0) { @@ -1273,14 +1307,24 @@ namespace { 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)) + void adjustOffsetAndIndex(EvalInfo &Info, const Expr *E, + const APSInt &Index, CharUnits ElementSize) { + // An index of 0 has no effect. (In C, adding 0 to a null pointer is UB, + // but we're not required to diagnose it and it's valid in C++.) + if (!Index) + return; + + // Compute the new offset in the appropriate width, wrapping at 64 bits. + // FIXME: When compiling for a 32-bit target, we should use 32-bit + // offsets. + uint64_t Offset64 = Offset.getQuantity(); + uint64_t ElemSize64 = ElementSize.getQuantity(); + uint64_t Index64 = Index.extOrTrunc(64).getZExtValue(); + Offset = CharUnits::fromQuantity(Offset64 + ElemSize64 * Index64); + + if (checkNullPointer(Info, E, CSK_ArrayIndex)) Designator.adjustIndex(Info, E, Index); - if (Index) - clearIsNullPointer(); + clearIsNullPointer(); } void adjustOffset(CharUnits N) { Offset += N; @@ -1411,6 +1455,16 @@ static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result); // Misc utilities //===----------------------------------------------------------------------===// +/// Negate an APSInt in place, converting it to a signed form if necessary, and +/// preserving its value (by extending by up to one bit as needed). +static void negateAsSigned(APSInt &Int) { + if (Int.isUnsigned() || Int.isMinSignedValue()) { + Int = Int.extend(Int.getBitWidth() + 1); + Int.setIsSigned(true); + } + Int = -Int; +} + /// Produce a string describing the given constexpr call. static void describeCall(CallStackFrame *Frame, raw_ostream &Out) { unsigned ArgIndex = 0; @@ -1458,13 +1512,6 @@ static bool EvaluateIgnoredValue(EvalInfo &Info, const Expr *E) { return true; } -/// Sign- or zero-extend a value to 64 bits. If it's already 64 bits, just -/// return its existing value. -static int64_t getExtValue(const APSInt &Value) { - return Value.isSigned() ? Value.getSExtValue() - : static_cast<int64_t>(Value.getZExtValue()); -} - /// Should this call expression be treated as a string literal? static bool IsStringLiteralCall(const CallExpr *E) { unsigned Builtin = E->getBuiltinCallee(); @@ -1617,6 +1664,19 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, return true; } +/// Member pointers are constant expressions unless they point to a +/// non-virtual dllimport member function. +static bool CheckMemberPointerConstantExpression(EvalInfo &Info, + SourceLocation Loc, + QualType Type, + const APValue &Value) { + const ValueDecl *Member = Value.getMemberPointerDecl(); + const auto *FD = dyn_cast_or_null<CXXMethodDecl>(Member); + if (!FD) + return true; + return FD->isVirtual() || !FD->hasAttr<DLLImportAttr>(); +} + /// Check that this core constant expression is of literal type, and if not, /// produce an appropriate diagnostic. static bool CheckLiteralType(EvalInfo &Info, const Expr *E, @@ -1709,6 +1769,9 @@ static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc, return CheckLValueConstantExpression(Info, DiagLoc, Type, LVal); } + if (Value.isMemberPointer()) + return CheckMemberPointerConstantExpression(Info, DiagLoc, Type, Value); + // Everything else is fine. return true; } @@ -2220,7 +2283,7 @@ static bool HandleSizeof(EvalInfo &Info, SourceLocation Loc, /// \param Adjustment - The adjustment, in objects of type EltTy, to add. static bool HandleLValueArrayAdjustment(EvalInfo &Info, const Expr *E, LValue &LVal, QualType EltTy, - int64_t Adjustment) { + APSInt Adjustment) { CharUnits SizeOfPointee; if (!HandleSizeof(Info, E->getExprLoc(), EltTy, SizeOfPointee)) return false; @@ -2229,6 +2292,13 @@ static bool HandleLValueArrayAdjustment(EvalInfo &Info, const Expr *E, return true; } +static bool HandleLValueArrayAdjustment(EvalInfo &Info, const Expr *E, + LValue &LVal, QualType EltTy, + int64_t Adjustment) { + return HandleLValueArrayAdjustment(Info, E, LVal, EltTy, + APSInt::get(Adjustment)); +} + /// Update an lvalue to refer to a component of a complex number. /// \param Info - Information about the ongoing evaluation. /// \param LVal - The lvalue to be updated. @@ -2247,6 +2317,10 @@ static bool HandleLValueComplexElement(EvalInfo &Info, const Expr *E, return true; } +static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, + QualType Type, const LValue &LVal, + APValue &RVal); + /// Try to evaluate the initializer for a variable declaration. /// /// \param Info Information about the ongoing evaluation. @@ -2258,6 +2332,7 @@ static bool HandleLValueComplexElement(EvalInfo &Info, const Expr *E, static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, const VarDecl *VD, CallStackFrame *Frame, APValue *&Result) { + // If this is a parameter to an active constexpr function call, perform // argument substitution. if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(VD)) { @@ -3191,9 +3266,9 @@ struct CompoundAssignSubobjectHandler { return false; } - int64_t Offset = getExtValue(RHS.getInt()); + APSInt Offset = RHS.getInt(); if (Opcode == BO_Sub) - Offset = -Offset; + negateAsSigned(Offset); LValue LVal; LVal.setFrom(Info.Ctx, Subobj); @@ -4148,6 +4223,10 @@ static bool HandleFunctionCall(SourceLocation CallLoc, return false; This->moveInto(Result); return true; + } else if (MD && isLambdaCallOperator(MD)) { + // We're in a lambda; determine the lambda capture field maps. + MD->getParent()->getCaptureFields(Frame.LambdaCaptureFields, + Frame.LambdaThisCaptureField); } StmtResult Ret = {Result, ResultSlot}; @@ -4363,8 +4442,14 @@ private: bool HandleConditionalOperator(const ConditionalOperator *E) { bool BoolResult; if (!EvaluateAsBooleanCondition(E->getCond(), BoolResult, Info)) { - if (Info.checkingPotentialConstantExpression() && Info.noteFailure()) + if (Info.checkingPotentialConstantExpression() && Info.noteFailure()) { CheckPotentialConstantConditional(E); + return false; + } + if (Info.noteFailure()) { + StmtVisitorTy::Visit(E->getTrueExpr()); + StmtVisitorTy::Visit(E->getFalseExpr()); + } return false; } @@ -5009,6 +5094,33 @@ bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { + + // If we are within a lambda's call operator, check whether the 'VD' referred + // to within 'E' actually represents a lambda-capture that maps to a + // data-member/field within the closure object, and if so, evaluate to the + // field or what the field refers to. + if (Info.CurrentCall && isLambdaCallOperator(Info.CurrentCall->Callee)) { + if (auto *FD = Info.CurrentCall->LambdaCaptureFields.lookup(VD)) { + if (Info.checkingPotentialConstantExpression()) + return false; + // Start with 'Result' referring to the complete closure object... + Result = *Info.CurrentCall->This; + // ... then update it to refer to the field of the closure object + // that represents the capture. + if (!HandleLValueMember(Info, E, Result, FD)) + return false; + // And if the field is of reference type, update 'Result' to refer to what + // the field refers to. + if (FD->getType()->isReferenceType()) { + APValue RVal; + if (!handleLValueToRValueConversion(Info, E, FD->getType(), Result, + RVal)) + return false; + Result.setFrom(Info.Ctx, RVal); + } + return true; + } + } CallStackFrame *Frame = nullptr; if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1) { // Only if a local variable was declared in the function currently being @@ -5155,15 +5267,19 @@ bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { if (E->getBase()->getType()->isVectorType()) return Error(E); - if (!evaluatePointer(E->getBase(), Result)) - return false; + bool Success = true; + if (!evaluatePointer(E->getBase(), Result)) { + if (!Info.noteFailure()) + return false; + Success = false; + } APSInt Index; if (!EvaluateInteger(E->getIdx(), Index, Info)) return false; - return HandleLValueArrayAdjustment(Info, E, Result, E->getType(), - getExtValue(Index)); + return Success && + HandleLValueArrayAdjustment(Info, E, Result, E->getType(), Index); } bool LValueExprEvaluator::VisitUnaryDeref(const UnaryOperator *E) { @@ -5376,8 +5492,8 @@ public: return true; } bool ZeroInitialization(const Expr *E) { - auto Offset = Info.Ctx.getTargetNullPointerValue(E->getType()); - Result.set((Expr*)nullptr, 0, false, true, Offset); + auto TargetVal = Info.Ctx.getTargetNullPointerValue(E->getType()); + Result.setNull(E->getType(), TargetVal); return true; } @@ -5386,8 +5502,11 @@ public: bool VisitUnaryAddrOf(const UnaryOperator *E); bool VisitObjCStringLiteral(const ObjCStringLiteral *E) { return Success(E); } - bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E) - { return Success(E); } + bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E) { + if (Info.noteFailure()) + EvaluateIgnoredValue(Info, E->getSubExpr()); + return Error(E); + } bool VisitAddrLabelExpr(const AddrLabelExpr *E) { return Success(E); } bool VisitCallExpr(const CallExpr *E); @@ -5409,6 +5528,27 @@ public: return false; } Result = *Info.CurrentCall->This; + // If we are inside a lambda's call operator, the 'this' expression refers + // to the enclosing '*this' object (either by value or reference) which is + // either copied into the closure object's field that represents the '*this' + // or refers to '*this'. + if (isLambdaCallOperator(Info.CurrentCall->Callee)) { + // Update 'Result' to refer to the data member/field of the closure object + // that represents the '*this' capture. + if (!HandleLValueMember(Info, E, Result, + Info.CurrentCall->LambdaThisCaptureField)) + return false; + // If we captured '*this' by reference, replace the field with its referent. + if (Info.CurrentCall->LambdaThisCaptureField->getType() + ->isPointerType()) { + APValue RVal; + if (!handleLValueToRValueConversion(Info, E, E->getType(), Result, + RVal)) + return false; + + Result.setFrom(Info.Ctx, RVal); + } + } return true; } @@ -5440,13 +5580,11 @@ bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (!EvaluateInteger(IExp, Offset, Info) || !EvalPtrOK) return false; - int64_t AdditionalOffset = getExtValue(Offset); if (E->getOpcode() == BO_Sub) - AdditionalOffset = -AdditionalOffset; + negateAsSigned(Offset); QualType Pointee = PExp->getType()->castAs<PointerType>()->getPointeeType(); - return HandleLValueArrayAdjustment(Info, E, Result, Pointee, - AdditionalOffset); + return HandleLValueArrayAdjustment(Info, E, Result, Pointee, Offset); } bool PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) { @@ -5576,6 +5714,8 @@ static CharUnits GetAlignOfType(EvalInfo &Info, QualType T) { T = Ref->getPointeeType(); // __alignof is defined to return the preferred alignment. + if (T.getQualifiers().hasUnaligned()) + return CharUnits::One(); return Info.Ctx.toCharUnitsFromBits( Info.Ctx.getPreferredTypeAlign(T.getTypePtr())); } @@ -5640,14 +5780,14 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, APSInt Alignment; if (!EvaluateInteger(E->getArg(1), Alignment, Info)) return false; - CharUnits Align = CharUnits::fromQuantity(getExtValue(Alignment)); + CharUnits Align = CharUnits::fromQuantity(Alignment.getZExtValue()); if (E->getNumArgs() > 2) { APSInt Offset; if (!EvaluateInteger(E->getArg(2), Offset, Info)) return false; - int64_t AdditionalOffset = -getExtValue(Offset); + int64_t AdditionalOffset = -Offset.getZExtValue(); OffsetResult.Offset += CharUnits::fromQuantity(AdditionalOffset); } @@ -5664,12 +5804,11 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(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: Add support to Diagnostic for long / long long. CCEDiag(E->getArg(0), diag::note_constexpr_baa_insufficient_alignment) << 0 - << (int) BaseAlignment.getQuantity() - << (unsigned) getExtValue(Alignment); + << (unsigned)BaseAlignment.getQuantity() + << (unsigned)Align.getQuantity(); return false; } } @@ -5677,18 +5816,14 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, // The offset must also have the correct alignment. if (OffsetResult.Offset.alignTo(Align) != OffsetResult.Offset) { Result.Designator.setInvalid(); - APSInt Offset(64, false); - Offset = OffsetResult.Offset.getQuantity(); - - if (OffsetResult.Base) - CCEDiag(E->getArg(0), - diag::note_constexpr_baa_insufficient_alignment) << 1 - << (int) getExtValue(Offset) << (unsigned) getExtValue(Alignment); - else - CCEDiag(E->getArg(0), - diag::note_constexpr_baa_value_insufficient_alignment) - << Offset << (unsigned) getExtValue(Alignment); + (OffsetResult.Base + ? CCEDiag(E->getArg(0), + diag::note_constexpr_baa_insufficient_alignment) << 1 + : CCEDiag(E->getArg(0), + diag::note_constexpr_baa_value_insufficient_alignment)) + << (int)OffsetResult.Offset.getQuantity() + << (unsigned)Align.getQuantity(); return false; } @@ -6245,14 +6380,40 @@ bool RecordExprEvaluator::VisitLambdaExpr(const LambdaExpr *E) { 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; + + const size_t NumFields = + std::distance(ClosureClass->field_begin(), ClosureClass->field_end()); + + assert(NumFields == (size_t)std::distance(E->capture_init_begin(), + E->capture_init_end()) && + "The number of lambda capture initializers should equal the number of " + "fields within the closure type"); + + Result = APValue(APValue::UninitStruct(), /*NumBases*/0, NumFields); + // Iterate through all the lambda's closure object's fields and initialize + // them. + auto *CaptureInitIt = E->capture_init_begin(); + const LambdaCapture *CaptureIt = ClosureClass->captures_begin(); + bool Success = true; + for (const auto *Field : ClosureClass->fields()) { + assert(CaptureInitIt != E->capture_init_end()); + // Get the initializer for this field + Expr *const CurFieldInit = *CaptureInitIt++; + + // If there is no initializer, either this is a VLA or an error has + // occurred. + if (!CurFieldInit) + return Error(E); + + APValue &FieldVal = Result.getStructField(Field->getFieldIndex()); + if (!EvaluateInPlace(FieldVal, Info, This, CurFieldInit)) { + if (!Info.keepEvaluatingAfterFailure()) + return false; + Success = false; + } + ++CaptureIt; } - // FIXME: Implement captures. - Result = APValue(APValue::UninitStruct(), /*NumBases*/0, /*NumFields*/0); - return true; + return Success; } static bool EvaluateRecord(const Expr *E, const LValue &This, @@ -6971,7 +7132,6 @@ static int EvaluateBuiltinClassifyType(const CallExpr *E, case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: case BuiltinType::OCLQueue: - case BuiltinType::OCLNDRange: case BuiltinType::OCLReserveID: case BuiltinType::Dependent: llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type"); @@ -7030,6 +7190,7 @@ static int EvaluateBuiltinClassifyType(const CallExpr *E, case Type::Vector: case Type::ExtVector: case Type::Auto: + case Type::DeducedTemplateSpecialization: case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: @@ -7948,6 +8109,19 @@ bool DataRecursiveIntBinOpEvaluator:: return true; } +static void addOrSubLValueAsInteger(APValue &LVal, const APSInt &Index, + bool IsSub) { + // Compute the new offset in the appropriate width, wrapping at 64 bits. + // FIXME: When compiling for a 32-bit target, we should use 32-bit + // offsets. + assert(!LVal.hasLValuePath() && "have designator for integer lvalue"); + CharUnits &Offset = LVal.getLValueOffset(); + uint64_t Offset64 = Offset.getQuantity(); + uint64_t Index64 = Index.extOrTrunc(64).getZExtValue(); + Offset = CharUnits::fromQuantity(IsSub ? Offset64 - Index64 + : Offset64 + Index64); +} + bool DataRecursiveIntBinOpEvaluator:: VisitBinOp(const EvalResult &LHSResult, const EvalResult &RHSResult, const BinaryOperator *E, APValue &Result) { @@ -7994,12 +8168,7 @@ bool DataRecursiveIntBinOpEvaluator:: // Handle cases like (unsigned long)&a + 4. if (E->isAdditiveOp() && LHSVal.isLValue() && RHSVal.isInt()) { Result = LHSVal; - CharUnits AdditionalOffset = - CharUnits::fromQuantity(RHSVal.getInt().getZExtValue()); - if (E->getOpcode() == BO_Add) - Result.getLValueOffset() += AdditionalOffset; - else - Result.getLValueOffset() -= AdditionalOffset; + addOrSubLValueAsInteger(Result, RHSVal.getInt(), E->getOpcode() == BO_Sub); return true; } @@ -8007,8 +8176,7 @@ bool DataRecursiveIntBinOpEvaluator:: if (E->getOpcode() == BO_Add && RHSVal.isLValue() && LHSVal.isInt()) { Result = RHSVal; - Result.getLValueOffset() += - CharUnits::fromQuantity(LHSVal.getInt().getZExtValue()); + addOrSubLValueAsInteger(Result, LHSVal.getInt(), /*IsSub*/false); return true; } @@ -9352,7 +9520,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { case BO_Mul: if (Result.isComplexFloat()) { // This is an implementation of complex multiplication according to the - // constraints laid out in C11 Annex G. The implemantion uses the + // constraints laid out in C11 Annex G. The implemention uses the // following naming scheme: // (a + ib) * (c + id) ComplexValue LHS = Result; @@ -9433,7 +9601,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { case BO_Div: if (Result.isComplexFloat()) { // This is an implementation of complex division according to the - // constraints laid out in C11 Annex G. The implemantion uses the + // constraints laid out in C11 Annex G. The implemention uses the // following naming scheme: // (a + ib) / (c + id) ComplexValue LHS = Result; @@ -9610,6 +9778,8 @@ public: bool Success(const APValue &V, const Expr *e) { return true; } + bool ZeroInitialization(const Expr *E) { return true; } + bool VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: @@ -9945,7 +10115,7 @@ bool Expr::EvalResult::isGlobalLValue() const { // Note that to reduce code duplication, this helper does no evaluation // itself; the caller checks whether the expression is evaluatable, and // in the rare cases where CheckICE actually cares about the evaluated -// value, it calls into Evalute. +// value, it calls into Evaluate. namespace { @@ -10067,6 +10237,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::LambdaExprClass: case Expr::CXXFoldExprClass: case Expr::CoawaitExprClass: + case Expr::DependentCoawaitExprClass: case Expr::CoyieldExprClass: return ICEDiag(IK_NotICE, E->getLocStart()); @@ -10169,6 +10340,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { } // OffsetOf falls through here. + LLVM_FALLTHROUGH; } case Expr::OffsetOfExprClass: { // Note that per C99, offsetof must be an ICE. And AFAIK, using @@ -10271,6 +10443,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { return Worst(LHSResult, RHSResult); } } + LLVM_FALLTHROUGH; } case Expr::ImplicitCastExprClass: case Expr::CStyleCastExprClass: diff --git a/contrib/llvm/tools/clang/lib/AST/ExternalASTMerger.cpp b/contrib/llvm/tools/clang/lib/AST/ExternalASTMerger.cpp new file mode 100644 index 0000000..4f4a997 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/AST/ExternalASTMerger.cpp @@ -0,0 +1,182 @@ +//===- ExternalASTMerger.cpp - Merging External AST Interface ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the ExternalASTMerger, which vends a combination of +// ASTs from several different ASTContext/FileManager pairs +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/ExternalASTMerger.h" + +using namespace clang; + +namespace { + +template <typename T> struct Source { + T t; + Source(T t) : t(t) {} + operator T() { return t; } + template <typename U = T> U &get() { return t; } + template <typename U = T> const U &get() const { return t; } + template <typename U> operator Source<U>() { return Source<U>(t); } +}; + +typedef std::pair<Source<NamedDecl *>, ASTImporter *> Candidate; + +class LazyASTImporter : public ASTImporter { +public: + LazyASTImporter(ASTContext &ToContext, FileManager &ToFileManager, + ASTContext &FromContext, FileManager &FromFileManager) + : ASTImporter(ToContext, ToFileManager, FromContext, FromFileManager, + /*MinimalImport=*/true) {} + Decl *Imported(Decl *From, Decl *To) override { + if (auto ToTag = dyn_cast<TagDecl>(To)) { + ToTag->setHasExternalLexicalStorage(); + ToTag->setMustBuildLookupTable(); + } else if (auto ToNamespace = dyn_cast<NamespaceDecl>(To)) { + ToNamespace->setHasExternalVisibleStorage(); + } + return ASTImporter::Imported(From, To); + } +}; + +Source<const DeclContext *> +LookupSameContext(Source<TranslationUnitDecl *> SourceTU, const DeclContext *DC, + ASTImporter &ReverseImporter) { + if (DC->isTranslationUnit()) { + return SourceTU; + } + Source<const DeclContext *> SourceParentDC = + LookupSameContext(SourceTU, DC->getParent(), ReverseImporter); + if (!SourceParentDC) { + // If we couldn't find the parent DC in this TranslationUnit, give up. + return nullptr; + } + auto ND = cast<NamedDecl>(DC); + DeclarationName Name = ND->getDeclName(); + Source<DeclarationName> SourceName = ReverseImporter.Import(Name); + DeclContext::lookup_result SearchResult = + SourceParentDC.get()->lookup(SourceName.get()); + size_t SearchResultSize = SearchResult.size(); + // Handle multiple candidates once we have a test for it. + // This may turn up when we import template specializations correctly. + assert(SearchResultSize < 2); + if (SearchResultSize == 0) { + // couldn't find the name, so we have to give up + return nullptr; + } else { + NamedDecl *SearchResultDecl = SearchResult[0]; + return dyn_cast<DeclContext>(SearchResultDecl); + } +} + +bool IsForwardDeclaration(Decl *D) { + assert(!isa<ObjCInterfaceDecl>(D)); // TODO handle this case + if (auto TD = dyn_cast<TagDecl>(D)) { + return !TD->isThisDeclarationADefinition(); + } else if (auto FD = dyn_cast<FunctionDecl>(D)) { + return !FD->isThisDeclarationADefinition(); + } else { + return false; + } +} + +template <typename CallbackType> +void ForEachMatchingDC( + const DeclContext *DC, + llvm::ArrayRef<ExternalASTMerger::ImporterPair> Importers, + CallbackType Callback) { + for (const ExternalASTMerger::ImporterPair &IP : Importers) { + Source<TranslationUnitDecl *> SourceTU = + IP.Forward->getFromContext().getTranslationUnitDecl(); + if (auto SourceDC = LookupSameContext(SourceTU, DC, *IP.Reverse)) + Callback(IP, SourceDC); + } +} + +bool HasDeclOfSameType(llvm::ArrayRef<Candidate> Decls, const Candidate &C) { + return llvm::any_of(Decls, [&](const Candidate &D) { + return C.first.get()->getKind() == D.first.get()->getKind(); + }); +} +} // end namespace + +ExternalASTMerger::ExternalASTMerger(const ImporterEndpoint &Target, + llvm::ArrayRef<ImporterEndpoint> Sources) { + for (const ImporterEndpoint &S : Sources) { + Importers.push_back( + {llvm::make_unique<LazyASTImporter>(Target.AST, Target.FM, S.AST, S.FM), + llvm::make_unique<ASTImporter>(S.AST, S.FM, Target.AST, Target.FM, + /*MinimalImport=*/true)}); + } +} + +bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC, + DeclarationName Name) { + llvm::SmallVector<NamedDecl *, 1> Decls; + llvm::SmallVector<Candidate, 4> CompleteDecls; + llvm::SmallVector<Candidate, 4> ForwardDecls; + + auto FilterFoundDecl = [&CompleteDecls, &ForwardDecls](const Candidate &C) { + if (IsForwardDeclaration(C.first.get())) { + if (!HasDeclOfSameType(ForwardDecls, C)) { + ForwardDecls.push_back(C); + } + } else { + CompleteDecls.push_back(C); + } + }; + + ForEachMatchingDC( + DC, Importers, + [&](const ImporterPair &IP, Source<const DeclContext *> SourceDC) { + DeclarationName FromName = IP.Reverse->Import(Name); + DeclContextLookupResult Result = SourceDC.get()->lookup(FromName); + for (NamedDecl *FromD : Result) { + FilterFoundDecl(std::make_pair(FromD, IP.Forward.get())); + } + }); + + llvm::ArrayRef<Candidate> DeclsToReport = + CompleteDecls.empty() ? ForwardDecls : CompleteDecls; + + if (DeclsToReport.empty()) { + return false; + } + + Decls.reserve(DeclsToReport.size()); + for (const Candidate &C : DeclsToReport) { + NamedDecl *d = cast<NamedDecl>(C.second->Import(C.first.get())); + assert(d); + Decls.push_back(d); + } + SetExternalVisibleDeclsForName(DC, Name, Decls); + return true; +} + +void ExternalASTMerger::FindExternalLexicalDecls( + const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant, + SmallVectorImpl<Decl *> &Result) { + ForEachMatchingDC( + DC, Importers, + [&](const ImporterPair &IP, Source<const DeclContext *> SourceDC) { + for (const Decl *SourceDecl : SourceDC.get()->decls()) { + if (IsKindWeWant(SourceDecl->getKind())) { + Decl *ImportedDecl = + IP.Forward->Import(const_cast<Decl *>(SourceDecl)); + assert(ImportedDecl->getDeclContext() == DC); + (void)ImportedDecl; + } + } + }); +} + diff --git a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp index e3de8c5..182d382 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp @@ -28,6 +28,11 @@ ExternalASTSource::getSourceDescriptor(unsigned ID) { return None; } +ExternalASTSource::ExtKind +ExternalASTSource::hasExternalDefinitions(const Decl *D) { + return EK_ReplyHazy; +} + ExternalASTSource::ASTSourceDescriptor::ASTSourceDescriptor(const Module &M) : Signature(M.Signature), ClangModule(&M) { if (M.Directory) diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp index ab3e49d..4e7c6c4 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp @@ -982,9 +982,8 @@ void CXXNameMangler::mangleFloat(const llvm::APFloat &f) { unsigned digitBitIndex = 4 * (numCharacters - stringIndex - 1); // Project out 4 bits starting at 'digitIndex'. - llvm::integerPart hexDigit - = valueBits.getRawData()[digitBitIndex / llvm::integerPartWidth]; - hexDigit >>= (digitBitIndex % llvm::integerPartWidth); + uint64_t hexDigit = valueBits.getRawData()[digitBitIndex / 64]; + hexDigit >>= (digitBitIndex % 64); hexDigit &= 0xF; // Map that over to a lowercase hex digit. @@ -1190,6 +1189,8 @@ void CXXNameMangler::mangleUnresolvedName( llvm_unreachable("Can't mangle a constructor name!"); case DeclarationName::CXXUsingDirective: llvm_unreachable("Can't mangle a using directive name!"); + case DeclarationName::CXXDeductionGuideName: + llvm_unreachable("Can't mangle a deduction guide name!"); case DeclarationName::ObjCMultiArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCZeroArgSelector: @@ -1419,6 +1420,9 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, writeAbiTags(ND, AdditionalAbiTags); break; + case DeclarationName::CXXDeductionGuideName: + llvm_unreachable("Can't mangle a deduction guide name!"); + case DeclarationName::CXXUsingDirective: llvm_unreachable("Can't mangle a using directive name!"); } @@ -1451,7 +1455,7 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND, Out << 'N'; if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND)) { Qualifiers MethodQuals = - Qualifiers::fromCVRMask(Method->getTypeQualifiers()); + Qualifiers::fromCVRUMask(Method->getTypeQualifiers()); // We do not consider restrict a distinguishing attribute for overloading // purposes so we must not mangle it. MethodQuals.removeRestrict(); @@ -1870,6 +1874,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, case Type::Paren: case Type::Attributed: case Type::Auto: + case Type::DeducedTemplateSpecialization: case Type::PackExpansion: case Type::ObjCObject: case Type::ObjCInterface: @@ -1996,6 +2001,7 @@ void CXXNameMangler::mangleOperatorName(DeclarationName Name, unsigned Arity) { switch (Name.getNameKind()) { case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: + case DeclarationName::CXXDeductionGuideName: case DeclarationName::CXXUsingDirective: case DeclarationName::Identifier: case DeclarationName::ObjCMultiArgSelector: @@ -2132,7 +2138,8 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) { } void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { - // Vendor qualifiers come first. + // Vendor qualifiers come first and if they are order-insensitive they must + // be emitted in reversed alphabetical order, see Itanium ABI 5.1.5. // Address space qualifiers start with an ordinary letter. if (Quals.hasAddressSpace()) { @@ -2152,10 +2159,12 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { } else { switch (AS) { default: llvm_unreachable("Not a language specific address space"); - // <OpenCL-addrspace> ::= "CL" [ "global" | "local" | "constant" ] + // <OpenCL-addrspace> ::= "CL" [ "global" | "local" | "constant | + // "generic" ] case LangAS::opencl_global: ASString = "CLglobal"; break; case LangAS::opencl_local: ASString = "CLlocal"; break; case LangAS::opencl_constant: ASString = "CLconstant"; break; + case LangAS::opencl_generic: ASString = "CLgeneric"; break; // <CUDA-addrspace> ::= "CU" [ "device" | "constant" | "shared" ] case LangAS::cuda_device: ASString = "CUdevice"; break; case LangAS::cuda_constant: ASString = "CUconstant"; break; @@ -2166,17 +2175,28 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { } // The ARC ownership qualifiers start with underscores. - switch (Quals.getObjCLifetime()) { // Objective-C ARC Extension: // // <type> ::= U "__strong" // <type> ::= U "__weak" // <type> ::= U "__autoreleasing" + // + // Note: we emit __weak first to preserve the order as + // required by the Itanium ABI. + if (Quals.getObjCLifetime() == Qualifiers::OCL_Weak) + mangleVendorQualifier("__weak"); + + // __unaligned (from -fms-extensions) + if (Quals.hasUnaligned()) + mangleVendorQualifier("__unaligned"); + + // Remaining ARC ownership qualifiers. + switch (Quals.getObjCLifetime()) { case Qualifiers::OCL_None: break; case Qualifiers::OCL_Weak: - mangleVendorQualifier("__weak"); + // Do nothing as we already handled this case above. break; case Qualifiers::OCL_Strong: @@ -2493,9 +2513,6 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::OCLQueue: Out << "9ocl_queue"; break; - case BuiltinType::OCLNDRange: - Out << "11ocl_ndrange"; - break; case BuiltinType::OCLReserveID: Out << "13ocl_reserveid"; break; @@ -2512,7 +2529,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) { case CC_X86ThisCall: case CC_X86VectorCall: case CC_X86Pascal: - case CC_X86_64Win64: + case CC_Win64: case CC_X86_64SysV: case CC_X86RegCall: case CC_AAPCS: @@ -3043,6 +3060,7 @@ void CXXNameMangler::mangleType(const DependentNameType *T) { // ::= Te <name> # dependent elaborated type specifier using // # 'enum' switch (T->getKeyword()) { + case ETK_None: case ETK_Typename: break; case ETK_Struct: @@ -3056,8 +3074,6 @@ void CXXNameMangler::mangleType(const DependentNameType *T) { case ETK_Enum: Out << "Te"; break; - default: - llvm_unreachable("unexpected keyword for dependent type name"); } // Typename types are always nested Out << 'N'; @@ -3146,6 +3162,16 @@ void CXXNameMangler::mangleType(const AutoType *T) { mangleType(D); } +void CXXNameMangler::mangleType(const DeducedTemplateSpecializationType *T) { + // FIXME: This is not the right mangling. We also need to include a scope + // here in some cases. + QualType D = T->getDeducedType(); + if (D.isNull()) + mangleUnscopedTemplateName(T->getTemplateName(), nullptr); + else + mangleType(D); +} + void CXXNameMangler::mangleType(const AtomicType *T) { // <type> ::= U <source-name> <type> # vendor extended type qualifier // (Until there's a standardized mangling...) @@ -3759,6 +3785,7 @@ recurse: Out << "v1U" << Kind.size() << Kind; } // Fall through to mangle the cast itself. + LLVM_FALLTHROUGH; case Expr::CStyleCastExprClass: mangleCastExpression(E, "cv"); @@ -4021,6 +4048,12 @@ recurse: mangleExpression(cast<CoawaitExpr>(E)->getOperand()); break; + case Expr::DependentCoawaitExprClass: + // FIXME: Propose a non-vendor mangling. + Out << "v18co_await"; + mangleExpression(cast<DependentCoawaitExpr>(E)->getOperand()); + break; + case Expr::CoyieldExprClass: // FIXME: Propose a non-vendor mangling. Out << "v18co_yield"; @@ -4305,7 +4338,7 @@ bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) { /// substitutions. static bool hasMangledSubstitutionQualifiers(QualType T) { Qualifiers Qs = T.getQualifiers(); - return Qs.getCVRQualifiers() || Qs.hasAddressSpace(); + return Qs.getCVRQualifiers() || Qs.hasAddressSpace() || Qs.hasUnaligned(); } bool CXXNameMangler::mangleSubstitution(QualType T) { @@ -4517,9 +4550,11 @@ CXXNameMangler::makeFunctionReturnTypeTags(const FunctionDecl *FD) { const FunctionProtoType *Proto = cast<FunctionProtoType>(FD->getType()->getAs<FunctionType>()); + FunctionTypeDepthState saved = TrackReturnTypeTags.FunctionTypeDepth.push(); TrackReturnTypeTags.FunctionTypeDepth.enterResultType(); TrackReturnTypeTags.mangleType(Proto->getReturnType()); TrackReturnTypeTags.FunctionTypeDepth.leaveResultType(); + TrackReturnTypeTags.FunctionTypeDepth.pop(saved); return TrackReturnTypeTags.AbiTagsRoot.getSortedUniqueUsedAbiTags(); } diff --git a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp index 05dd886..00d50c0 100644 --- a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp @@ -262,9 +262,13 @@ void MangleContext::mangleObjCMethodNameWithoutSize(const ObjCMethodDecl *MD, const ObjCContainerDecl *CD = dyn_cast<ObjCContainerDecl>(MD->getDeclContext()); assert (CD && "Missing container decl in GetNameForMethod"); - OS << (MD->isInstanceMethod() ? '-' : '+') << '[' << CD->getName(); - if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(CD)) + OS << (MD->isInstanceMethod() ? '-' : '+') << '['; + if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(CD)) { + OS << CID->getClassInterface()->getName(); OS << '(' << *CID << ')'; + } else { + OS << CD->getName(); + } OS << ' '; MD->getSelector().print(OS); OS << ']'; diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp index 76c368d..24b16f8 100644 --- a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp @@ -942,6 +942,9 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, break; } + case DeclarationName::CXXDeductionGuideName: + llvm_unreachable("Can't mangle a deduction guide name!"); + case DeclarationName::CXXUsingDirective: llvm_unreachable("Can't mangle a using directive name!"); } @@ -963,16 +966,71 @@ void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) { } if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) { - DiagnosticsEngine &Diags = Context.getDiags(); - unsigned DiagID = - Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle a local inside this block yet"); - Diags.Report(BD->getLocation(), DiagID); - - // FIXME: This is completely, utterly, wrong; see ItaniumMangle - // for how this should be done. - Out << "__block_invoke" << Context.getBlockId(BD, false); - Out << '@'; + auto Discriminate = + [](StringRef Name, const unsigned Discriminator, + const unsigned ParameterDiscriminator) -> std::string { + std::string Buffer; + llvm::raw_string_ostream Stream(Buffer); + Stream << Name; + if (Discriminator) + Stream << '_' << Discriminator; + if (ParameterDiscriminator) + Stream << '_' << ParameterDiscriminator; + return Stream.str(); + }; + + unsigned Discriminator = BD->getBlockManglingNumber(); + if (!Discriminator) + Discriminator = Context.getBlockId(BD, /*Local=*/false); + + // Mangle the parameter position as a discriminator to deal with unnamed + // parameters. Rather than mangling the unqualified parameter name, + // always use the position to give a uniform mangling. + unsigned ParameterDiscriminator = 0; + if (const auto *MC = BD->getBlockManglingContextDecl()) + if (const auto *P = dyn_cast<ParmVarDecl>(MC)) + if (const auto *F = dyn_cast<FunctionDecl>(P->getDeclContext())) + ParameterDiscriminator = + F->getNumParams() - P->getFunctionScopeIndex(); + + DC = getEffectiveDeclContext(BD); + + Out << '?'; + mangleSourceName(Discriminate("_block_invoke", Discriminator, + ParameterDiscriminator)); + // If we have a block mangling context, encode that now. This allows us + // to discriminate between named static data initializers in the same + // scope. This is handled differently from parameters, which use + // positions to discriminate between multiple instances. + if (const auto *MC = BD->getBlockManglingContextDecl()) + if (!isa<ParmVarDecl>(MC)) + if (const auto *ND = dyn_cast<NamedDecl>(MC)) + mangleUnqualifiedName(ND); + // MS ABI and Itanium manglings are in inverted scopes. In the case of a + // RecordDecl, mangle the entire scope hierachy at this point rather than + // just the unqualified name to get the ordering correct. + if (const auto *RD = dyn_cast<RecordDecl>(DC)) + mangleName(RD); + else + Out << '@'; + // void __cdecl + Out << "YAX"; + // struct __block_literal * + Out << 'P'; + // __ptr64 + if (PointersAre64Bit) + Out << 'E'; + Out << 'A'; + mangleArtificalTagType(TTK_Struct, + Discriminate("__block_literal", Discriminator, + ParameterDiscriminator)); + Out << "@Z"; + + // If the effective context was a Record, we have fully mangled the + // qualified name and do not need to continue. + if (isa<RecordDecl>(DC)) + break; + continue; } else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) { mangleObjCMethodName(Method); } else if (isa<NamedDecl>(DC)) { @@ -1686,6 +1744,8 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, // ::= _N # bool // _O # <array in parameter> // ::= _T # __float80 (Intel) + // ::= _S # char16_t + // ::= _U # char32_t // ::= _W # wchar_t // ::= _Z # __float80 (Digital Mars) switch (T->getKind()) { @@ -1797,10 +1857,6 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, Out << "PA"; mangleArtificalTagType(TTK_Struct, "ocl_queue"); break; - case BuiltinType::OCLNDRange: - Out << "PA"; - mangleArtificalTagType(TTK_Struct, "ocl_ndrange"); - break; case BuiltinType::OCLReserveID: Out << "PA"; mangleArtificalTagType(TTK_Struct, "ocl_reserveid"); @@ -1887,14 +1943,18 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, // <return-type> ::= <type> // ::= @ # structors (they have no declared return type) if (IsStructor) { - 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. - // FIXME: This is a temporary hack. - // Maybe should fix the FunctionType creation instead? - Out << (PointersAre64Bit ? "PEAXI@Z" : "PAXI@Z"); - return; + if (isa<CXXDestructorDecl>(D) && isStructorDecl(D)) { + // The scalar deleting destructor takes an extra int argument which is not + // reflected in the AST. + if (StructorType == Dtor_Deleting) { + Out << (PointersAre64Bit ? "PEAXI@Z" : "PAXI@Z"); + return; + } + // The vbase destructor returns void which is not reflected in the AST. + if (StructorType == Dtor_Complete) { + Out << "XXZ"; + return; + } } if (IsCtorClosure) { // Default constructor closure and copy constructor closure both return @@ -1954,7 +2014,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, // Happens for function pointer type arguments for example. for (unsigned I = 0, E = Proto->getNumParams(); I != E; ++I) { mangleArgumentType(Proto->getParamType(I), Range); - // Mangle each pass_object_size parameter as if it's a paramater of enum + // Mangle each pass_object_size parameter as if it's a parameter of enum // type passed directly after the parameter with the pass_object_size // attribute. The aforementioned enum's name is __pass_object_size, and we // pretend it resides in a top-level namespace called __clang. @@ -2002,13 +2062,20 @@ void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) { // <global-function> ::= Y # global near // ::= Z # global far if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { + bool IsVirtual = MD->isVirtual(); + // When mangling vbase destructor variants, ignore whether or not the + // underlying destructor was defined to be virtual. + if (isa<CXXDestructorDecl>(MD) && isStructorDecl(MD) && + StructorType == Dtor_Complete) { + IsVirtual = false; + } switch (MD->getAccess()) { case AS_none: llvm_unreachable("Unsupported access specifier"); case AS_private: if (MD->isStatic()) Out << 'C'; - else if (MD->isVirtual()) + else if (IsVirtual) Out << 'E'; else Out << 'A'; @@ -2016,7 +2083,7 @@ void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) { case AS_protected: if (MD->isStatic()) Out << 'K'; - else if (MD->isVirtual()) + else if (IsVirtual) Out << 'M'; else Out << 'I'; @@ -2024,7 +2091,7 @@ void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) { case AS_public: if (MD->isStatic()) Out << 'S'; - else if (MD->isVirtual()) + else if (IsVirtual) Out << 'U'; else Out << 'Q'; @@ -2055,7 +2122,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) { switch (CC) { default: llvm_unreachable("Unsupported CC for mangling"); - case CC_X86_64Win64: + case CC_Win64: case CC_X86_64SysV: case CC_C: Out << 'A'; break; case CC_X86Pascal: Out << 'C'; break; @@ -2474,6 +2541,17 @@ void MicrosoftCXXNameMangler::mangleType(const AutoType *T, Qualifiers, << Range; } +void MicrosoftCXXNameMangler::mangleType( + const DeducedTemplateSpecializationType *T, Qualifiers, SourceRange Range) { + assert(T->getDeducedType().isNull() && "expecting a dependent type!"); + + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this deduced class template specialization type yet"); + Diags.Report(Range.getBegin(), DiagID) + << Range; +} + void MicrosoftCXXNameMangler::mangleType(const AtomicType *T, Qualifiers, SourceRange Range) { QualType ValueType = T->getValueType(); @@ -2997,14 +3075,14 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, // N.B. The length is in terms of bytes, not characters. Mangler.mangleNumber(SL->getByteLength() + SL->getCharByteWidth()); - auto GetLittleEndianByte = [&Mangler, &SL](unsigned Index) { + auto GetLittleEndianByte = [&SL](unsigned Index) { unsigned CharByteWidth = SL->getCharByteWidth(); uint32_t CodeUnit = SL->getCodeUnit(Index / CharByteWidth); unsigned OffsetInCodeUnit = Index % CharByteWidth; return static_cast<char>((CodeUnit >> (8 * OffsetInCodeUnit)) & 0xff); }; - auto GetBigEndianByte = [&Mangler, &SL](unsigned Index) { + auto GetBigEndianByte = [&SL](unsigned Index) { unsigned CharByteWidth = SL->getCharByteWidth(); uint32_t CodeUnit = SL->getCodeUnit(Index / CharByteWidth); unsigned OffsetInCodeUnit = (CharByteWidth - 1) - (Index % CharByteWidth); diff --git a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp index ac2a8d3..e7c8c16 100644 --- a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp @@ -453,7 +453,6 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const { case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: case BuiltinType::OCLQueue: - case BuiltinType::OCLNDRange: case BuiltinType::OCLReserveID: case BuiltinType::BoundMember: case BuiltinType::Dependent: diff --git a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp index 514c7c9..e2e0dbe 100644 --- a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp +++ b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp @@ -290,6 +290,7 @@ NestedNameSpecifier::print(raw_ostream &OS, case TypeSpecWithTemplate: OS << "template "; // Fall through to print the type. + LLVM_FALLTHROUGH; case TypeSpec: { const Type *T = getAsType(); diff --git a/contrib/llvm/tools/clang/lib/AST/ODRHash.cpp b/contrib/llvm/tools/clang/lib/AST/ODRHash.cpp new file mode 100644 index 0000000..121724a --- /dev/null +++ b/contrib/llvm/tools/clang/lib/AST/ODRHash.cpp @@ -0,0 +1,636 @@ +//===-- ODRHash.cpp - Hashing to diagnose ODR failures ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file implements the ODRHash class, which calculates a hash based +/// on AST nodes, which is stable across different runs. +/// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ODRHash.h" + +#include "clang/AST/DeclVisitor.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/StmtVisitor.h" +#include "clang/AST/TypeVisitor.h" + +using namespace clang; + +void ODRHash::AddStmt(const Stmt *S) { + assert(S && "Expecting non-null pointer."); + S->ProcessODRHash(ID, *this); +} + +void ODRHash::AddIdentifierInfo(const IdentifierInfo *II) { + assert(II && "Expecting non-null pointer."); + ID.AddString(II->getName()); +} + +void ODRHash::AddDeclarationName(DeclarationName Name) { + AddBoolean(Name.isEmpty()); + if (Name.isEmpty()) + return; + + auto Kind = Name.getNameKind(); + ID.AddInteger(Kind); + switch (Kind) { + case DeclarationName::Identifier: + AddIdentifierInfo(Name.getAsIdentifierInfo()); + break; + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: { + Selector S = Name.getObjCSelector(); + AddBoolean(S.isNull()); + AddBoolean(S.isKeywordSelector()); + AddBoolean(S.isUnarySelector()); + unsigned NumArgs = S.getNumArgs(); + for (unsigned i = 0; i < NumArgs; ++i) { + AddIdentifierInfo(S.getIdentifierInfoForSlot(i)); + } + break; + } + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + AddQualType(Name.getCXXNameType()); + break; + case DeclarationName::CXXOperatorName: + ID.AddInteger(Name.getCXXOverloadedOperator()); + break; + case DeclarationName::CXXLiteralOperatorName: + AddIdentifierInfo(Name.getCXXLiteralIdentifier()); + break; + case DeclarationName::CXXConversionFunctionName: + AddQualType(Name.getCXXNameType()); + break; + case DeclarationName::CXXUsingDirective: + break; + case DeclarationName::CXXDeductionGuideName: { + auto *Template = Name.getCXXDeductionGuideTemplate(); + AddBoolean(Template); + if (Template) { + AddDecl(Template); + } + } + } +} + +void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) { + assert(NNS && "Expecting non-null pointer."); + const auto *Prefix = NNS->getPrefix(); + AddBoolean(Prefix); + if (Prefix) { + AddNestedNameSpecifier(Prefix); + } + auto Kind = NNS->getKind(); + ID.AddInteger(Kind); + switch (Kind) { + case NestedNameSpecifier::Identifier: + AddIdentifierInfo(NNS->getAsIdentifier()); + break; + case NestedNameSpecifier::Namespace: + AddDecl(NNS->getAsNamespace()); + break; + case NestedNameSpecifier::NamespaceAlias: + AddDecl(NNS->getAsNamespaceAlias()); + break; + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + AddType(NNS->getAsType()); + break; + case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: + break; + } +} + +void ODRHash::AddTemplateName(TemplateName Name) { + auto Kind = Name.getKind(); + ID.AddInteger(Kind); + + switch (Kind) { + case TemplateName::Template: + AddDecl(Name.getAsTemplateDecl()); + break; + // TODO: Support these cases. + case TemplateName::OverloadedTemplate: + case TemplateName::QualifiedTemplate: + case TemplateName::DependentTemplate: + case TemplateName::SubstTemplateTemplateParm: + case TemplateName::SubstTemplateTemplateParmPack: + break; + } +} + +void ODRHash::AddTemplateArgument(TemplateArgument TA) { + const auto Kind = TA.getKind(); + ID.AddInteger(Kind); + + switch (Kind) { + case TemplateArgument::Null: + llvm_unreachable("Expected valid TemplateArgument"); + case TemplateArgument::Type: + AddQualType(TA.getAsType()); + break; + case TemplateArgument::Declaration: + case TemplateArgument::NullPtr: + case TemplateArgument::Integral: + break; + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + AddTemplateName(TA.getAsTemplateOrTemplatePattern()); + break; + case TemplateArgument::Expression: + AddStmt(TA.getAsExpr()); + break; + case TemplateArgument::Pack: + ID.AddInteger(TA.pack_size()); + for (auto SubTA : TA.pack_elements()) { + AddTemplateArgument(SubTA); + } + break; + } +} + +void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) {} + +void ODRHash::clear() { + DeclMap.clear(); + TypeMap.clear(); + Bools.clear(); + ID.clear(); +} + +unsigned ODRHash::CalculateHash() { + // Append the bools to the end of the data segment backwards. This allows + // for the bools data to be compressed 32 times smaller compared to using + // ID.AddBoolean + const unsigned unsigned_bits = sizeof(unsigned) * CHAR_BIT; + const unsigned size = Bools.size(); + const unsigned remainder = size % unsigned_bits; + const unsigned loops = size / unsigned_bits; + auto I = Bools.rbegin(); + unsigned value = 0; + for (unsigned i = 0; i < remainder; ++i) { + value <<= 1; + value |= *I; + ++I; + } + ID.AddInteger(value); + + for (unsigned i = 0; i < loops; ++i) { + value = 0; + for (unsigned j = 0; j < unsigned_bits; ++j) { + value <<= 1; + value |= *I; + ++I; + } + ID.AddInteger(value); + } + + assert(I == Bools.rend()); + Bools.clear(); + return ID.ComputeHash(); +} + +// Process a Decl pointer. Add* methods call back into ODRHash while Visit* +// methods process the relevant parts of the Decl. +class ODRDeclVisitor : public ConstDeclVisitor<ODRDeclVisitor> { + typedef ConstDeclVisitor<ODRDeclVisitor> Inherited; + llvm::FoldingSetNodeID &ID; + ODRHash &Hash; + +public: + ODRDeclVisitor(llvm::FoldingSetNodeID &ID, ODRHash &Hash) + : ID(ID), Hash(Hash) {} + + void AddStmt(const Stmt *S) { + Hash.AddBoolean(S); + if (S) { + Hash.AddStmt(S); + } + } + + void AddIdentifierInfo(const IdentifierInfo *II) { + Hash.AddBoolean(II); + if (II) { + Hash.AddIdentifierInfo(II); + } + } + + void AddQualType(QualType T) { + Hash.AddQualType(T); + } + + void AddDecl(const Decl *D) { + Hash.AddBoolean(D); + if (D) { + Hash.AddDecl(D); + } + } + + void Visit(const Decl *D) { + ID.AddInteger(D->getKind()); + Inherited::Visit(D); + } + + void VisitNamedDecl(const NamedDecl *D) { + Hash.AddDeclarationName(D->getDeclName()); + Inherited::VisitNamedDecl(D); + } + + void VisitValueDecl(const ValueDecl *D) { + if (!isa<FunctionDecl>(D)) { + AddQualType(D->getType()); + } + Inherited::VisitValueDecl(D); + } + + void VisitVarDecl(const VarDecl *D) { + Hash.AddBoolean(D->isStaticLocal()); + Hash.AddBoolean(D->isConstexpr()); + const bool HasInit = D->hasInit(); + Hash.AddBoolean(HasInit); + if (HasInit) { + AddStmt(D->getInit()); + } + Inherited::VisitVarDecl(D); + } + + void VisitParmVarDecl(const ParmVarDecl *D) { + // TODO: Handle default arguments. + Inherited::VisitParmVarDecl(D); + } + + void VisitAccessSpecDecl(const AccessSpecDecl *D) { + ID.AddInteger(D->getAccess()); + Inherited::VisitAccessSpecDecl(D); + } + + void VisitStaticAssertDecl(const StaticAssertDecl *D) { + AddStmt(D->getAssertExpr()); + AddStmt(D->getMessage()); + + Inherited::VisitStaticAssertDecl(D); + } + + void VisitFieldDecl(const FieldDecl *D) { + const bool IsBitfield = D->isBitField(); + Hash.AddBoolean(IsBitfield); + + if (IsBitfield) { + AddStmt(D->getBitWidth()); + } + + Hash.AddBoolean(D->isMutable()); + AddStmt(D->getInClassInitializer()); + + Inherited::VisitFieldDecl(D); + } + + void VisitFunctionDecl(const FunctionDecl *D) { + ID.AddInteger(D->getStorageClass()); + Hash.AddBoolean(D->isInlineSpecified()); + Hash.AddBoolean(D->isVirtualAsWritten()); + Hash.AddBoolean(D->isPure()); + Hash.AddBoolean(D->isDeletedAsWritten()); + + ID.AddInteger(D->param_size()); + + for (auto *Param : D->parameters()) { + Hash.AddSubDecl(Param); + } + + AddQualType(D->getReturnType()); + + Inherited::VisitFunctionDecl(D); + } + + void VisitCXXMethodDecl(const CXXMethodDecl *D) { + Hash.AddBoolean(D->isConst()); + Hash.AddBoolean(D->isVolatile()); + + Inherited::VisitCXXMethodDecl(D); + } + + void VisitTypedefNameDecl(const TypedefNameDecl *D) { + AddQualType(D->getUnderlyingType()); + + Inherited::VisitTypedefNameDecl(D); + } + + void VisitTypedefDecl(const TypedefDecl *D) { + Inherited::VisitTypedefDecl(D); + } + + void VisitTypeAliasDecl(const TypeAliasDecl *D) { + Inherited::VisitTypeAliasDecl(D); + } + + void VisitFriendDecl(const FriendDecl *D) { + TypeSourceInfo *TSI = D->getFriendType(); + Hash.AddBoolean(TSI); + if (TSI) { + AddQualType(TSI->getType()); + } else { + AddDecl(D->getFriendDecl()); + } + } +}; + +// Only allow a small portion of Decl's to be processed. Remove this once +// all Decl's can be handled. +bool ODRHash::isWhitelistedDecl(const Decl *D, const CXXRecordDecl *Parent) { + if (D->isImplicit()) return false; + if (D->getDeclContext() != Parent) return false; + + switch (D->getKind()) { + default: + return false; + case Decl::AccessSpec: + case Decl::CXXConstructor: + case Decl::CXXDestructor: + case Decl::CXXMethod: + case Decl::Field: + case Decl::Friend: + case Decl::StaticAssert: + case Decl::TypeAlias: + case Decl::Typedef: + case Decl::Var: + return true; + } +} + +void ODRHash::AddSubDecl(const Decl *D) { + assert(D && "Expecting non-null pointer."); + AddDecl(D); + + ODRDeclVisitor(ID, *this).Visit(D); +} + +void ODRHash::AddCXXRecordDecl(const CXXRecordDecl *Record) { + assert(Record && Record->hasDefinition() && + "Expected non-null record to be a definition."); + + const DeclContext *DC = Record; + while (DC) { + if (isa<ClassTemplateSpecializationDecl>(DC)) { + return; + } + DC = DC->getParent(); + } + + AddDecl(Record); + + // Filter out sub-Decls which will not be processed in order to get an + // accurate count of Decl's. + llvm::SmallVector<const Decl *, 16> Decls; + for (const Decl *SubDecl : Record->decls()) { + if (isWhitelistedDecl(SubDecl, Record)) { + Decls.push_back(SubDecl); + } + } + + ID.AddInteger(Decls.size()); + for (auto SubDecl : Decls) { + AddSubDecl(SubDecl); + } +} + +void ODRHash::AddDecl(const Decl *D) { + assert(D && "Expecting non-null pointer."); + auto Result = DeclMap.insert(std::make_pair(D, DeclMap.size())); + ID.AddInteger(Result.first->second); + // On first encounter of a Decl pointer, process it. Every time afterwards, + // only the index value is needed. + if (!Result.second) { + return; + } + + ID.AddInteger(D->getKind()); + + if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) { + AddDeclarationName(ND->getDeclName()); + } +} + +// Process a Type pointer. Add* methods call back into ODRHash while Visit* +// methods process the relevant parts of the Type. +class ODRTypeVisitor : public TypeVisitor<ODRTypeVisitor> { + typedef TypeVisitor<ODRTypeVisitor> Inherited; + llvm::FoldingSetNodeID &ID; + ODRHash &Hash; + +public: + ODRTypeVisitor(llvm::FoldingSetNodeID &ID, ODRHash &Hash) + : ID(ID), Hash(Hash) {} + + void AddStmt(Stmt *S) { + Hash.AddBoolean(S); + if (S) { + Hash.AddStmt(S); + } + } + + void AddDecl(Decl *D) { + Hash.AddBoolean(D); + if (D) { + Hash.AddDecl(D); + } + } + + void AddQualType(QualType T) { + Hash.AddQualType(T); + } + + void AddType(const Type *T) { + Hash.AddBoolean(T); + if (T) { + Hash.AddType(T); + } + } + + void AddNestedNameSpecifier(const NestedNameSpecifier *NNS) { + Hash.AddBoolean(NNS); + if (NNS) { + Hash.AddNestedNameSpecifier(NNS); + } + } + + void AddIdentifierInfo(const IdentifierInfo *II) { + Hash.AddBoolean(II); + if (II) { + Hash.AddIdentifierInfo(II); + } + } + + void VisitQualifiers(Qualifiers Quals) { + ID.AddInteger(Quals.getAsOpaqueValue()); + } + + void Visit(const Type *T) { + ID.AddInteger(T->getTypeClass()); + Inherited::Visit(T); + } + + void VisitType(const Type *T) {} + + void VisitAdjustedType(const AdjustedType *T) { + AddQualType(T->getOriginalType()); + AddQualType(T->getAdjustedType()); + VisitType(T); + } + + void VisitDecayedType(const DecayedType *T) { + AddQualType(T->getDecayedType()); + AddQualType(T->getPointeeType()); + VisitAdjustedType(T); + } + + void VisitArrayType(const ArrayType *T) { + AddQualType(T->getElementType()); + ID.AddInteger(T->getSizeModifier()); + VisitQualifiers(T->getIndexTypeQualifiers()); + VisitType(T); + } + void VisitConstantArrayType(const ConstantArrayType *T) { + T->getSize().Profile(ID); + VisitArrayType(T); + } + + void VisitDependentSizedArrayType(const DependentSizedArrayType *T) { + AddStmt(T->getSizeExpr()); + VisitArrayType(T); + } + + void VisitIncompleteArrayType(const IncompleteArrayType *T) { + VisitArrayType(T); + } + + void VisitVariableArrayType(const VariableArrayType *T) { + AddStmt(T->getSizeExpr()); + VisitArrayType(T); + } + + void VisitBuiltinType(const BuiltinType *T) { + ID.AddInteger(T->getKind()); + VisitType(T); + } + + void VisitFunctionType(const FunctionType *T) { + AddQualType(T->getReturnType()); + T->getExtInfo().Profile(ID); + Hash.AddBoolean(T->isConst()); + Hash.AddBoolean(T->isVolatile()); + Hash.AddBoolean(T->isRestrict()); + VisitType(T); + } + + void VisitFunctionNoProtoType(const FunctionNoProtoType *T) { + VisitFunctionType(T); + } + + void VisitFunctionProtoType(const FunctionProtoType *T) { + ID.AddInteger(T->getNumParams()); + for (auto ParamType : T->getParamTypes()) + AddQualType(ParamType); + + VisitFunctionType(T); + } + + void VisitTypedefType(const TypedefType *T) { + AddDecl(T->getDecl()); + QualType UnderlyingType = T->getDecl()->getUnderlyingType(); + VisitQualifiers(UnderlyingType.getQualifiers()); + while (const TypedefType *Underlying = + dyn_cast<TypedefType>(UnderlyingType.getTypePtr())) { + UnderlyingType = Underlying->getDecl()->getUnderlyingType(); + } + AddType(UnderlyingType.getTypePtr()); + VisitType(T); + } + + void VisitTagType(const TagType *T) { + AddDecl(T->getDecl()); + VisitType(T); + } + + void VisitRecordType(const RecordType *T) { VisitTagType(T); } + void VisitEnumType(const EnumType *T) { VisitTagType(T); } + + void VisitTypeWithKeyword(const TypeWithKeyword *T) { + ID.AddInteger(T->getKeyword()); + VisitType(T); + }; + + void VisitDependentNameType(const DependentNameType *T) { + AddNestedNameSpecifier(T->getQualifier()); + AddIdentifierInfo(T->getIdentifier()); + VisitTypeWithKeyword(T); + } + + void VisitDependentTemplateSpecializationType( + const DependentTemplateSpecializationType *T) { + AddIdentifierInfo(T->getIdentifier()); + AddNestedNameSpecifier(T->getQualifier()); + ID.AddInteger(T->getNumArgs()); + for (const auto &TA : T->template_arguments()) { + Hash.AddTemplateArgument(TA); + } + VisitTypeWithKeyword(T); + } + + void VisitElaboratedType(const ElaboratedType *T) { + AddNestedNameSpecifier(T->getQualifier()); + AddQualType(T->getNamedType()); + VisitTypeWithKeyword(T); + } + + void VisitTemplateSpecializationType(const TemplateSpecializationType *T) { + ID.AddInteger(T->getNumArgs()); + for (const auto &TA : T->template_arguments()) { + Hash.AddTemplateArgument(TA); + } + Hash.AddTemplateName(T->getTemplateName()); + VisitType(T); + } + + void VisitTemplateTypeParmType(const TemplateTypeParmType *T) { + ID.AddInteger(T->getDepth()); + ID.AddInteger(T->getIndex()); + Hash.AddBoolean(T->isParameterPack()); + AddDecl(T->getDecl()); + } +}; + +void ODRHash::AddType(const Type *T) { + assert(T && "Expecting non-null pointer."); + auto Result = TypeMap.insert(std::make_pair(T, TypeMap.size())); + ID.AddInteger(Result.first->second); + // On first encounter of a Type pointer, process it. Every time afterwards, + // only the index value is needed. + if (!Result.second) { + return; + } + + ODRTypeVisitor(ID, *this).Visit(T); +} + +void ODRHash::AddQualType(QualType T) { + AddBoolean(T.isNull()); + if (T.isNull()) + return; + SplitQualType split = T.split(); + ID.AddInteger(split.Quals.getAsOpaqueValue()); + AddType(split.Ty); +} + +void ODRHash::AddBoolean(bool Value) { + Bools.push_back(Value); +} diff --git a/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp b/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp index a28b9f3..2c4d159 100644 --- a/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp +++ b/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp @@ -46,13 +46,21 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { return static_cast<const OMPLastprivateClause *>(C); case OMPC_reduction: return static_cast<const OMPReductionClause *>(C); + case OMPC_task_reduction: + return static_cast<const OMPTaskReductionClause *>(C); case OMPC_linear: return static_cast<const OMPLinearClause *>(C); + case OMPC_if: + return static_cast<const OMPIfClause *>(C); + case OMPC_num_threads: + return static_cast<const OMPNumThreadsClause *>(C); + case OMPC_num_teams: + return static_cast<const OMPNumTeamsClause *>(C); + case OMPC_thread_limit: + return static_cast<const OMPThreadLimitClause *>(C); case OMPC_default: case OMPC_proc_bind: - case OMPC_if: case OMPC_final: - case OMPC_num_threads: case OMPC_safelen: case OMPC_simdlen: case OMPC_collapse: @@ -77,8 +85,6 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { case OMPC_threads: case OMPC_simd: case OMPC_map: - case OMPC_num_teams: - case OMPC_thread_limit: case OMPC_priority: case OMPC_grainsize: case OMPC_nogroup: @@ -108,6 +114,8 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) return static_cast<const OMPLastprivateClause *>(C); case OMPC_reduction: return static_cast<const OMPReductionClause *>(C); + case OMPC_task_reduction: + return static_cast<const OMPTaskReductionClause *>(C); case OMPC_linear: return static_cast<const OMPLinearClause *>(C); case OMPC_schedule: @@ -501,6 +509,59 @@ OMPReductionClause *OMPReductionClause::CreateEmpty(const ASTContext &C, return new (Mem) OMPReductionClause(N); } +void OMPTaskReductionClause::setPrivates(ArrayRef<Expr *> Privates) { + assert(Privates.size() == varlist_size() && + "Number of private copies is not the same as the preallocated buffer"); + std::copy(Privates.begin(), Privates.end(), varlist_end()); +} + +void OMPTaskReductionClause::setLHSExprs(ArrayRef<Expr *> LHSExprs) { + assert( + LHSExprs.size() == varlist_size() && + "Number of LHS expressions is not the same as the preallocated buffer"); + std::copy(LHSExprs.begin(), LHSExprs.end(), getPrivates().end()); +} + +void OMPTaskReductionClause::setRHSExprs(ArrayRef<Expr *> RHSExprs) { + assert( + RHSExprs.size() == varlist_size() && + "Number of RHS expressions is not the same as the preallocated buffer"); + std::copy(RHSExprs.begin(), RHSExprs.end(), getLHSExprs().end()); +} + +void OMPTaskReductionClause::setReductionOps(ArrayRef<Expr *> ReductionOps) { + assert(ReductionOps.size() == varlist_size() && "Number of task reduction " + "expressions is not the same " + "as the preallocated buffer"); + std::copy(ReductionOps.begin(), ReductionOps.end(), getRHSExprs().end()); +} + +OMPTaskReductionClause *OMPTaskReductionClause::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, + ArrayRef<Expr *> Privates, ArrayRef<Expr *> LHSExprs, + ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps, Stmt *PreInit, + Expr *PostUpdate) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size())); + OMPTaskReductionClause *Clause = new (Mem) OMPTaskReductionClause( + StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo); + Clause->setVarRefs(VL); + Clause->setPrivates(Privates); + Clause->setLHSExprs(LHSExprs); + Clause->setRHSExprs(RHSExprs); + Clause->setReductionOps(ReductionOps); + Clause->setPreInitStmt(PreInit); + Clause->setPostUpdateExpr(PostUpdate); + return Clause; +} + +OMPTaskReductionClause *OMPTaskReductionClause::CreateEmpty(const ASTContext &C, + unsigned N) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * N)); + return new (Mem) OMPTaskReductionClause(N); +} + OMPFlushClause *OMPFlushClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp index cf981be..c0b9cad 100644 --- a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp @@ -3073,6 +3073,41 @@ uint64_t ASTContext::getFieldOffset(const ValueDecl *VD) const { return OffsetInBits; } +uint64_t ASTContext::lookupFieldBitOffset(const ObjCInterfaceDecl *OID, + const ObjCImplementationDecl *ID, + const ObjCIvarDecl *Ivar) const { + const ObjCInterfaceDecl *Container = Ivar->getContainingInterface(); + + // FIXME: We should eliminate the need to have ObjCImplementationDecl passed + // in here; it should never be necessary because that should be the lexical + // decl context for the ivar. + + // If we know have an implementation (and the ivar is in it) then + // look up in the implementation layout. + const ASTRecordLayout *RL; + if (ID && declaresSameEntity(ID->getClassInterface(), Container)) + RL = &getASTObjCImplementationLayout(ID); + else + RL = &getASTObjCInterfaceLayout(Container); + + // Compute field index. + // + // FIXME: The index here is closely tied to how ASTContext::getObjCLayout is + // implemented. This should be fixed to get the information from the layout + // directly. + unsigned Index = 0; + + for (const ObjCIvarDecl *IVD = Container->all_declared_ivar_begin(); + IVD; IVD = IVD->getNextIvar()) { + if (Ivar == IVD) + break; + ++Index; + } + assert(Index < RL->getFieldCount() && "Ivar is not inside record layout!"); + + return RL->getFieldOffset(Index); +} + /// getObjCLayout - Get or compute information about the layout of the /// given interface. /// diff --git a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp index 697cdc3..2367cad 100644 --- a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp @@ -1083,7 +1083,7 @@ CapturedStmt *CapturedStmt::CreateDeserialized(const ASTContext &Context, } Stmt::child_range CapturedStmt::children() { - // Children are captured field initilizers. + // Children are captured field initializers. return child_range(getStoredStmts(), getStoredStmts() + NumCaptures); } @@ -1112,7 +1112,7 @@ void CapturedStmt::setCapturedRegionKind(CapturedRegionKind Kind) { bool CapturedStmt::capturesVariable(const VarDecl *Var) const { for (const auto &I : captures()) { - if (!I.capturesVariable()) + if (!I.capturesVariable() && !I.capturesVariableByCopy()) continue; // This does not handle variable redeclarations. This should be diff --git a/contrib/llvm/tools/clang/lib/AST/StmtCXX.cpp b/contrib/llvm/tools/clang/lib/AST/StmtCXX.cpp index 4a04fc2..666f5dc 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtCXX.cpp @@ -86,3 +86,46 @@ VarDecl *CXXForRangeStmt::getLoopVariable() { const VarDecl *CXXForRangeStmt::getLoopVariable() const { return const_cast<CXXForRangeStmt *>(this)->getLoopVariable(); } + +CoroutineBodyStmt *CoroutineBodyStmt::Create( + const ASTContext &C, CoroutineBodyStmt::CtorArgs const &Args) { + std::size_t Size = totalSizeToAlloc<Stmt *>( + CoroutineBodyStmt::FirstParamMove + Args.ParamMoves.size()); + + void *Mem = C.Allocate(Size, alignof(CoroutineBodyStmt)); + return new (Mem) CoroutineBodyStmt(Args); +} + +CoroutineBodyStmt *CoroutineBodyStmt::Create(const ASTContext &C, EmptyShell, + unsigned NumParams) { + std::size_t Size = totalSizeToAlloc<Stmt *>( + CoroutineBodyStmt::FirstParamMove + NumParams); + + void *Mem = C.Allocate(Size, alignof(CoroutineBodyStmt)); + auto *Result = new (Mem) CoroutineBodyStmt(CtorArgs()); + Result->NumParams = NumParams; + auto *ParamBegin = Result->getStoredStmts() + SubStmt::FirstParamMove; + std::uninitialized_fill(ParamBegin, ParamBegin + NumParams, + static_cast<Stmt *>(nullptr)); + return Result; +} + +CoroutineBodyStmt::CoroutineBodyStmt(CoroutineBodyStmt::CtorArgs const &Args) + : Stmt(CoroutineBodyStmtClass), NumParams(Args.ParamMoves.size()) { + Stmt **SubStmts = getStoredStmts(); + SubStmts[CoroutineBodyStmt::Body] = Args.Body; + SubStmts[CoroutineBodyStmt::Promise] = Args.Promise; + SubStmts[CoroutineBodyStmt::InitSuspend] = Args.InitialSuspend; + SubStmts[CoroutineBodyStmt::FinalSuspend] = Args.FinalSuspend; + SubStmts[CoroutineBodyStmt::OnException] = Args.OnException; + SubStmts[CoroutineBodyStmt::OnFallthrough] = Args.OnFallthrough; + SubStmts[CoroutineBodyStmt::Allocate] = Args.Allocate; + SubStmts[CoroutineBodyStmt::Deallocate] = Args.Deallocate; + SubStmts[CoroutineBodyStmt::ReturnValue] = Args.ReturnValue; + SubStmts[CoroutineBodyStmt::ResultDecl] = Args.ResultDecl; + SubStmts[CoroutineBodyStmt::ReturnStmt] = Args.ReturnStmt; + SubStmts[CoroutineBodyStmt::ReturnStmtOnAllocFailure] = + Args.ReturnStmtOnAllocFailure; + std::copy(Args.ParamMoves.begin(), Args.ParamMoves.end(), + const_cast<Stmt **>(getParamMoves().data())); +} diff --git a/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp b/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp index 880817a..1dcb4fd 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp @@ -147,8 +147,6 @@ OMPForDirective::Create(const ASTContext &C, SourceLocation StartLoc, 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); @@ -199,8 +197,6 @@ OMPForSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc, 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); @@ -364,8 +360,6 @@ OMPParallelForDirective *OMPParallelForDirective::Create( 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); @@ -415,8 +409,6 @@ OMPParallelForSimdDirective *OMPParallelForSimdDirective::Create( 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); @@ -530,23 +522,28 @@ OMPTaskwaitDirective *OMPTaskwaitDirective::CreateEmpty(const ASTContext &C, return new (Mem) OMPTaskwaitDirective(); } -OMPTaskgroupDirective *OMPTaskgroupDirective::Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation EndLoc, - Stmt *AssociatedStmt) { - unsigned Size = llvm::alignTo(sizeof(OMPTaskgroupDirective), alignof(Stmt *)); +OMPTaskgroupDirective *OMPTaskgroupDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { + unsigned Size = llvm::alignTo(sizeof(OMPTaskgroupDirective) + + sizeof(OMPClause *) * Clauses.size(), + alignof(Stmt *)); void *Mem = C.Allocate(Size + sizeof(Stmt *)); OMPTaskgroupDirective *Dir = - new (Mem) OMPTaskgroupDirective(StartLoc, EndLoc); + new (Mem) OMPTaskgroupDirective(StartLoc, EndLoc, Clauses.size()); Dir->setAssociatedStmt(AssociatedStmt); + Dir->setClauses(Clauses); return Dir; } OMPTaskgroupDirective *OMPTaskgroupDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell) { - unsigned Size = llvm::alignTo(sizeof(OMPTaskgroupDirective), alignof(Stmt *)); + unsigned Size = llvm::alignTo(sizeof(OMPTaskgroupDirective) + + sizeof(OMPClause *) * NumClauses, + alignof(Stmt *)); void *Mem = C.Allocate(Size + sizeof(Stmt *)); - return new (Mem) OMPTaskgroupDirective(); + return new (Mem) OMPTaskgroupDirective(NumClauses); } OMPCancellationPointDirective *OMPCancellationPointDirective::Create( @@ -751,8 +748,6 @@ OMPTargetParallelForDirective *OMPTargetParallelForDirective::Create( 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); @@ -894,8 +889,6 @@ OMPTaskLoopDirective *OMPTaskLoopDirective::Create( 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); @@ -945,8 +938,6 @@ OMPTaskLoopSimdDirective *OMPTaskLoopSimdDirective::Create( 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); @@ -995,8 +986,6 @@ OMPDistributeDirective *OMPDistributeDirective::Create( 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); @@ -1071,12 +1060,21 @@ OMPDistributeParallelForDirective *OMPDistributeParallelForDirective::Create( Dir->setNumIterations(Exprs.NumIterations); Dir->setPrevLowerBoundVariable(Exprs.PrevLB); Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setDistInc(Exprs.DistInc); + Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); Dir->setPreInits(Exprs.PreInits); + Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB); + Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB); + Dir->setCombinedEnsureUpperBound(Exprs.DistCombinedFields.EUB); + Dir->setCombinedInit(Exprs.DistCombinedFields.Init); + Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); + Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); + Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); return Dir; } @@ -1127,12 +1125,21 @@ OMPDistributeParallelForSimdDirective::Create( Dir->setNumIterations(Exprs.NumIterations); Dir->setPrevLowerBoundVariable(Exprs.PrevLB); Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setDistInc(Exprs.DistInc); + Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); Dir->setPreInits(Exprs.PreInits); + Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB); + Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB); + Dir->setCombinedEnsureUpperBound(Exprs.DistCombinedFields.EUB); + Dir->setCombinedInit(Exprs.DistCombinedFields.Init); + Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); + Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); + Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); return Dir; } @@ -1180,8 +1187,6 @@ OMPDistributeSimdDirective *OMPDistributeSimdDirective::Create( 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); @@ -1234,8 +1239,6 @@ OMPTargetParallelForSimdDirective *OMPTargetParallelForSimdDirective::Create( 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); @@ -1328,8 +1331,6 @@ OMPTeamsDistributeDirective *OMPTeamsDistributeDirective::Create( 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); @@ -1381,8 +1382,6 @@ OMPTeamsDistributeSimdDirective *OMPTeamsDistributeSimdDirective::Create( 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); @@ -1438,12 +1437,21 @@ OMPTeamsDistributeParallelForSimdDirective::Create( Dir->setNumIterations(Exprs.NumIterations); Dir->setPrevLowerBoundVariable(Exprs.PrevLB); Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setDistInc(Exprs.DistInc); + Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); Dir->setPreInits(Exprs.PreInits); + Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB); + Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB); + Dir->setCombinedEnsureUpperBound(Exprs.DistCombinedFields.EUB); + Dir->setCombinedInit(Exprs.DistCombinedFields.Init); + Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); + Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); + Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); return Dir; } @@ -1496,12 +1504,21 @@ OMPTeamsDistributeParallelForDirective::Create( Dir->setNumIterations(Exprs.NumIterations); Dir->setPrevLowerBoundVariable(Exprs.PrevLB); Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setDistInc(Exprs.DistInc); + Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); Dir->setPreInits(Exprs.PreInits); + Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB); + Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB); + Dir->setCombinedEnsureUpperBound(Exprs.DistCombinedFields.EUB); + Dir->setCombinedInit(Exprs.DistCombinedFields.Init); + Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); + Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); + Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); return Dir; } @@ -1574,8 +1591,6 @@ OMPTargetTeamsDistributeDirective *OMPTargetTeamsDistributeDirective::Create( 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); @@ -1634,12 +1649,21 @@ OMPTargetTeamsDistributeParallelForDirective::Create( Dir->setNumIterations(Exprs.NumIterations); Dir->setPrevLowerBoundVariable(Exprs.PrevLB); Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setDistInc(Exprs.DistInc); + Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); Dir->setPreInits(Exprs.PreInits); + Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB); + Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB); + Dir->setCombinedEnsureUpperBound(Exprs.DistCombinedFields.EUB); + Dir->setCombinedInit(Exprs.DistCombinedFields.Init); + Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); + Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); + Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); return Dir; } @@ -1695,12 +1719,21 @@ OMPTargetTeamsDistributeParallelForSimdDirective::Create( Dir->setNumIterations(Exprs.NumIterations); Dir->setPrevLowerBoundVariable(Exprs.PrevLB); Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setDistInc(Exprs.DistInc); + Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); Dir->setPreInits(Exprs.PreInits); + Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB); + Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB); + Dir->setCombinedEnsureUpperBound(Exprs.DistCombinedFields.EUB); + Dir->setCombinedInit(Exprs.DistCombinedFields.Init); + Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); + Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); + Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); return Dir; } @@ -1751,8 +1784,6 @@ OMPTargetTeamsDistributeSimdDirective::Create( 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); diff --git a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp index 1ba1aa4..5ebaa32 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp @@ -836,6 +836,29 @@ void OMPClausePrinter::VisitOMPReductionClause(OMPReductionClause *Node) { } } +void OMPClausePrinter::VisitOMPTaskReductionClause( + OMPTaskReductionClause *Node) { + if (!Node->varlist_empty()) { + OS << "task_reduction("; + NestedNameSpecifier *QualifierLoc = + Node->getQualifierLoc().getNestedNameSpecifier(); + OverloadedOperatorKind OOK = + Node->getNameInfo().getName().getCXXOverloadedOperator(); + if (QualifierLoc == nullptr && OOK != OO_None) { + // Print reduction identifier in C format + OS << getOperatorSpelling(OOK); + } else { + // Use C++ format + if (QualifierLoc != nullptr) + QualifierLoc->print(OS, Policy); + OS << Node->getNameInfo(); + } + OS << ":"; + VisitOMPClauseList(Node, ' '); + OS << ")"; + } +} + void OMPClausePrinter::VisitOMPLinearClause(OMPLinearClause *Node) { if (!Node->varlist_empty()) { OS << "linear"; @@ -1081,7 +1104,7 @@ void StmtPrinter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *Node) { } void StmtPrinter::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *Node) { - Indent() << "#pragma omp taskgroup"; + Indent() << "#pragma omp taskgroup "; PrintOMPExecutableDirective(Node); } @@ -2475,6 +2498,13 @@ void StmtPrinter::VisitCoawaitExpr(CoawaitExpr *S) { PrintExpr(S->getOperand()); } + +void StmtPrinter::VisitDependentCoawaitExpr(DependentCoawaitExpr *S) { + OS << "co_await "; + PrintExpr(S->getOperand()); +} + + void StmtPrinter::VisitCoyieldExpr(CoyieldExpr *S) { OS << "co_yield "; PrintExpr(S->getOperand()); diff --git a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp index bcd2e96..7ec0d1d 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp @@ -19,20 +19,22 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" +#include "clang/AST/ODRHash.h" #include "clang/AST/StmtVisitor.h" #include "llvm/ADT/FoldingSet.h" using namespace clang; namespace { class StmtProfiler : public ConstStmtVisitor<StmtProfiler> { + protected: llvm::FoldingSetNodeID &ID; - const ASTContext &Context; bool Canonical; public: - StmtProfiler(llvm::FoldingSetNodeID &ID, const ASTContext &Context, - bool Canonical) - : ID(ID), Context(Context), Canonical(Canonical) { } + StmtProfiler(llvm::FoldingSetNodeID &ID, bool Canonical) + : ID(ID), Canonical(Canonical) {} + + virtual ~StmtProfiler() {} void VisitStmt(const Stmt *S); @@ -41,22 +43,25 @@ namespace { /// \brief Visit a declaration that is referenced within an expression /// or statement. - void VisitDecl(const Decl *D); + virtual void VisitDecl(const Decl *D) = 0; /// \brief Visit a type that is referenced within an expression or /// statement. - void VisitType(QualType T); + virtual void VisitType(QualType T) = 0; /// \brief Visit a name that occurs within an expression or statement. - void VisitName(DeclarationName Name); + virtual void VisitName(DeclarationName Name) = 0; + + /// \brief Visit identifiers that are not in Decl's or Type's. + virtual void VisitIdentifierInfo(IdentifierInfo *II) = 0; /// \brief Visit a nested-name-specifier that occurs within an expression /// or statement. - void VisitNestedNameSpecifier(NestedNameSpecifier *NNS); + virtual void VisitNestedNameSpecifier(NestedNameSpecifier *NNS) = 0; /// \brief Visit a template name that occurs within an expression or /// statement. - void VisitTemplateName(TemplateName Name); + virtual void VisitTemplateName(TemplateName Name) = 0; /// \brief Visit template arguments that occur within an expression or /// statement. @@ -66,6 +71,127 @@ namespace { /// \brief Visit a single template argument. void VisitTemplateArgument(const TemplateArgument &Arg); }; + + class StmtProfilerWithPointers : public StmtProfiler { + const ASTContext &Context; + + public: + StmtProfilerWithPointers(llvm::FoldingSetNodeID &ID, + const ASTContext &Context, bool Canonical) + : StmtProfiler(ID, Canonical), Context(Context) {} + private: + void VisitDecl(const Decl *D) override { + ID.AddInteger(D ? D->getKind() : 0); + + if (Canonical && D) { + if (const NonTypeTemplateParmDecl *NTTP = + dyn_cast<NonTypeTemplateParmDecl>(D)) { + ID.AddInteger(NTTP->getDepth()); + ID.AddInteger(NTTP->getIndex()); + ID.AddBoolean(NTTP->isParameterPack()); + VisitType(NTTP->getType()); + return; + } + + if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) { + // The Itanium C++ ABI uses the type, scope depth, and scope + // index of a parameter when mangling expressions that involve + // function parameters, so we will use the parameter's type for + // establishing function parameter identity. That way, our + // definition of "equivalent" (per C++ [temp.over.link]) is at + // least as strong as the definition of "equivalent" used for + // name mangling. + VisitType(Parm->getType()); + ID.AddInteger(Parm->getFunctionScopeDepth()); + ID.AddInteger(Parm->getFunctionScopeIndex()); + return; + } + + if (const TemplateTypeParmDecl *TTP = + dyn_cast<TemplateTypeParmDecl>(D)) { + ID.AddInteger(TTP->getDepth()); + ID.AddInteger(TTP->getIndex()); + ID.AddBoolean(TTP->isParameterPack()); + return; + } + + if (const TemplateTemplateParmDecl *TTP = + dyn_cast<TemplateTemplateParmDecl>(D)) { + ID.AddInteger(TTP->getDepth()); + ID.AddInteger(TTP->getIndex()); + ID.AddBoolean(TTP->isParameterPack()); + return; + } + } + + ID.AddPointer(D ? D->getCanonicalDecl() : nullptr); + } + + void VisitType(QualType T) override { + if (Canonical && !T.isNull()) + T = Context.getCanonicalType(T); + + ID.AddPointer(T.getAsOpaquePtr()); + } + + void VisitName(DeclarationName Name) override { + ID.AddPointer(Name.getAsOpaquePtr()); + } + + void VisitIdentifierInfo(IdentifierInfo *II) override { + ID.AddPointer(II); + } + + void VisitNestedNameSpecifier(NestedNameSpecifier *NNS) override { + if (Canonical) + NNS = Context.getCanonicalNestedNameSpecifier(NNS); + ID.AddPointer(NNS); + } + + void VisitTemplateName(TemplateName Name) override { + if (Canonical) + Name = Context.getCanonicalTemplateName(Name); + + Name.Profile(ID); + } + }; + + class StmtProfilerWithoutPointers : public StmtProfiler { + ODRHash &Hash; + public: + StmtProfilerWithoutPointers(llvm::FoldingSetNodeID &ID, ODRHash &Hash) + : StmtProfiler(ID, false), Hash(Hash) {} + + private: + void VisitType(QualType T) override { + Hash.AddQualType(T); + } + + void VisitName(DeclarationName Name) override { + Hash.AddDeclarationName(Name); + } + void VisitIdentifierInfo(IdentifierInfo *II) override { + ID.AddBoolean(II); + if (II) { + Hash.AddIdentifierInfo(II); + } + } + void VisitDecl(const Decl *D) override { + ID.AddBoolean(D); + if (D) { + Hash.AddDecl(D); + } + } + void VisitTemplateName(TemplateName Name) override { + Hash.AddTemplateName(Name); + } + void VisitNestedNameSpecifier(NestedNameSpecifier *NNS) override { + ID.AddBoolean(NNS); + if (NNS) { + Hash.AddNestedNameSpecifier(NNS); + } + } + }; } void StmtProfiler::VisitStmt(const Stmt *S) { @@ -283,6 +409,7 @@ void OMPClauseProfiler::VistOMPClauseWithPostUpdate( } void OMPClauseProfiler::VisitOMPIfClause(const OMPIfClause *C) { + VistOMPClauseWithPreInit(C); if (C->getCondition()) Profiler->VisitStmt(C->getCondition()); } @@ -293,6 +420,7 @@ void OMPClauseProfiler::VisitOMPFinalClause(const OMPFinalClause *C) { } void OMPClauseProfiler::VisitOMPNumThreadsClause(const OMPNumThreadsClause *C) { + VistOMPClauseWithPreInit(C); if (C->getNumThreads()) Profiler->VisitStmt(C->getNumThreads()); } @@ -421,6 +549,30 @@ void OMPClauseProfiler::VisitOMPReductionClause( Profiler->VisitStmt(E); } } +void OMPClauseProfiler::VisitOMPTaskReductionClause( + const OMPTaskReductionClause *C) { + Profiler->VisitNestedNameSpecifier( + C->getQualifierLoc().getNestedNameSpecifier()); + Profiler->VisitName(C->getNameInfo().getName()); + VisitOMPClauseList(C); + VistOMPClauseWithPostUpdate(C); + for (auto *E : C->privates()) { + if (E) + Profiler->VisitStmt(E); + } + for (auto *E : C->lhs_exprs()) { + if (E) + Profiler->VisitStmt(E); + } + for (auto *E : C->rhs_exprs()) { + if (E) + Profiler->VisitStmt(E); + } + for (auto *E : C->reduction_ops()) { + if (E) + Profiler->VisitStmt(E); + } +} void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) { VisitOMPClauseList(C); VistOMPClauseWithPostUpdate(C); @@ -495,11 +647,13 @@ void OMPClauseProfiler::VisitOMPMapClause(const OMPMapClause *C) { VisitOMPClauseList(C); } void OMPClauseProfiler::VisitOMPNumTeamsClause(const OMPNumTeamsClause *C) { + VistOMPClauseWithPreInit(C); if (C->getNumTeams()) Profiler->VisitStmt(C->getNumTeams()); } void OMPClauseProfiler::VisitOMPThreadLimitClause( const OMPThreadLimitClause *C) { + VistOMPClauseWithPreInit(C); if (C->getThreadLimit()) Profiler->VisitStmt(C->getThreadLimit()); } @@ -849,7 +1003,7 @@ void StmtProfiler::VisitOffsetOfExpr(const OffsetOfExpr *S) { break; case OffsetOfNode::Identifier: - ID.AddPointer(ON.getFieldName()); + VisitIdentifierInfo(ON.getFieldName()); break; case OffsetOfNode::Base: @@ -857,7 +1011,7 @@ void StmtProfiler::VisitOffsetOfExpr(const OffsetOfExpr *S) { break; } } - + VisitExpr(S); } @@ -1234,6 +1388,15 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S, llvm_unreachable("Invalid overloaded operator expression"); } +#if defined(_MSC_VER) +#if _MSC_VER == 1911 +// Work around https://developercommunity.visualstudio.com/content/problem/84002/clang-cl-when-built-with-vc-2017-crashes-cause-vc.html +// MSVC 2017 update 3 miscompiles this function, and a clang built with it +// will crash in stage 2 of a bootstrap build. +#pragma optimize("", off) +#endif +#endif + void StmtProfiler::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) { if (S->isTypeDependent()) { // Type-dependent operator calls are profiled like their underlying @@ -1266,6 +1429,12 @@ void StmtProfiler::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) { ID.AddInteger(S->getOperator()); } +#if defined(_MSC_VER) +#if _MSC_VER == 1911 +#pragma optimize("", on) +#endif +#endif + void StmtProfiler::VisitCXXMemberCallExpr(const CXXMemberCallExpr *S) { VisitCallExpr(S); } @@ -1447,7 +1616,7 @@ StmtProfiler::VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *S) { if (S->getDestroyedTypeInfo()) VisitType(S->getDestroyedType()); else - ID.AddPointer(S->getDestroyedTypeIdentifier()); + VisitIdentifierInfo(S->getDestroyedTypeIdentifier()); } void StmtProfiler::VisitOverloadExpr(const OverloadExpr *S) { @@ -1595,6 +1764,10 @@ void StmtProfiler::VisitCoawaitExpr(const CoawaitExpr *S) { VisitExpr(S); } +void StmtProfiler::VisitDependentCoawaitExpr(const DependentCoawaitExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitCoyieldExpr(const CoyieldExpr *S) { VisitExpr(S); } @@ -1697,77 +1870,6 @@ void StmtProfiler::VisitObjCAvailabilityCheckExpr( VisitExpr(S); } -void StmtProfiler::VisitDecl(const Decl *D) { - ID.AddInteger(D? D->getKind() : 0); - - if (Canonical && D) { - if (const NonTypeTemplateParmDecl *NTTP = - dyn_cast<NonTypeTemplateParmDecl>(D)) { - ID.AddInteger(NTTP->getDepth()); - ID.AddInteger(NTTP->getIndex()); - ID.AddBoolean(NTTP->isParameterPack()); - VisitType(NTTP->getType()); - return; - } - - if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) { - // The Itanium C++ ABI uses the type, scope depth, and scope - // index of a parameter when mangling expressions that involve - // function parameters, so we will use the parameter's type for - // establishing function parameter identity. That way, our - // definition of "equivalent" (per C++ [temp.over.link]) is at - // least as strong as the definition of "equivalent" used for - // name mangling. - VisitType(Parm->getType()); - ID.AddInteger(Parm->getFunctionScopeDepth()); - ID.AddInteger(Parm->getFunctionScopeIndex()); - return; - } - - if (const TemplateTypeParmDecl *TTP = - dyn_cast<TemplateTypeParmDecl>(D)) { - ID.AddInteger(TTP->getDepth()); - ID.AddInteger(TTP->getIndex()); - ID.AddBoolean(TTP->isParameterPack()); - return; - } - - if (const TemplateTemplateParmDecl *TTP = - dyn_cast<TemplateTemplateParmDecl>(D)) { - ID.AddInteger(TTP->getDepth()); - ID.AddInteger(TTP->getIndex()); - ID.AddBoolean(TTP->isParameterPack()); - return; - } - } - - ID.AddPointer(D? D->getCanonicalDecl() : nullptr); -} - -void StmtProfiler::VisitType(QualType T) { - if (Canonical) - T = Context.getCanonicalType(T); - - ID.AddPointer(T.getAsOpaquePtr()); -} - -void StmtProfiler::VisitName(DeclarationName Name) { - ID.AddPointer(Name.getAsOpaquePtr()); -} - -void StmtProfiler::VisitNestedNameSpecifier(NestedNameSpecifier *NNS) { - if (Canonical) - NNS = Context.getCanonicalNestedNameSpecifier(NNS); - ID.AddPointer(NNS); -} - -void StmtProfiler::VisitTemplateName(TemplateName Name) { - if (Canonical) - Name = Context.getCanonicalTemplateName(Name); - - Name.Profile(ID); -} - void StmtProfiler::VisitTemplateArguments(const TemplateArgumentLoc *Args, unsigned NumArgs) { ID.AddInteger(NumArgs); @@ -1817,6 +1919,12 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) { void Stmt::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical) const { - StmtProfiler Profiler(ID, Context, Canonical); + StmtProfilerWithPointers Profiler(ID, Context, Canonical); + Profiler.Visit(this); +} + +void Stmt::ProcessODRHash(llvm::FoldingSetNodeID &ID, + class ODRHash &Hash) const { + StmtProfilerWithoutPointers Profiler(ID, Hash); Profiler.Visit(this); } diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp index 099f939..e4998c3 100644 --- a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp @@ -453,10 +453,6 @@ LLVM_DUMP_METHOD void TemplateArgument::dump() const { dump(llvm::errs()); } // TemplateArgumentLoc Implementation //===----------------------------------------------------------------------===// -TemplateArgumentLocInfo::TemplateArgumentLocInfo() { - memset((void*)this, 0, sizeof(TemplateArgumentLocInfo)); -} - SourceRange TemplateArgumentLoc::getSourceRange() const { switch (Argument.getKind()) { case TemplateArgument::Expression: diff --git a/contrib/llvm/tools/clang/lib/AST/Type.cpp b/contrib/llvm/tools/clang/lib/AST/Type.cpp index 0d0cd2e..d21781d 100644 --- a/contrib/llvm/tools/clang/lib/AST/Type.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Type.cpp @@ -1344,7 +1344,7 @@ Optional<ArrayRef<QualType>> Type::getObjCSubstitutions( } else if (getAs<BlockPointerType>()) { ASTContext &ctx = dc->getParentASTContext(); objectType = ctx.getObjCObjectType(ctx.ObjCBuiltinIdTy, { }, { }) - ->castAs<ObjCObjectType>();; + ->castAs<ObjCObjectType>(); } else { objectType = getAs<ObjCObjectType>(); } @@ -1559,61 +1559,79 @@ TagDecl *Type::getAsTagDecl() const { } namespace { - class GetContainedAutoVisitor : - public TypeVisitor<GetContainedAutoVisitor, AutoType*> { + class GetContainedDeducedTypeVisitor : + public TypeVisitor<GetContainedDeducedTypeVisitor, Type*> { + bool Syntactic; public: - using TypeVisitor<GetContainedAutoVisitor, AutoType*>::Visit; - AutoType *Visit(QualType T) { + GetContainedDeducedTypeVisitor(bool Syntactic = false) + : Syntactic(Syntactic) {} + + using TypeVisitor<GetContainedDeducedTypeVisitor, Type*>::Visit; + Type *Visit(QualType T) { if (T.isNull()) return nullptr; return Visit(T.getTypePtr()); } - // The 'auto' type itself. - AutoType *VisitAutoType(const AutoType *AT) { - return const_cast<AutoType*>(AT); + // The deduced type itself. + Type *VisitDeducedType(const DeducedType *AT) { + return const_cast<DeducedType*>(AT); } // Only these types can contain the desired 'auto' type. - AutoType *VisitPointerType(const PointerType *T) { + Type *VisitElaboratedType(const ElaboratedType *T) { + return Visit(T->getNamedType()); + } + Type *VisitPointerType(const PointerType *T) { return Visit(T->getPointeeType()); } - AutoType *VisitBlockPointerType(const BlockPointerType *T) { + Type *VisitBlockPointerType(const BlockPointerType *T) { return Visit(T->getPointeeType()); } - AutoType *VisitReferenceType(const ReferenceType *T) { + Type *VisitReferenceType(const ReferenceType *T) { return Visit(T->getPointeeTypeAsWritten()); } - AutoType *VisitMemberPointerType(const MemberPointerType *T) { + Type *VisitMemberPointerType(const MemberPointerType *T) { return Visit(T->getPointeeType()); } - AutoType *VisitArrayType(const ArrayType *T) { + Type *VisitArrayType(const ArrayType *T) { return Visit(T->getElementType()); } - AutoType *VisitDependentSizedExtVectorType( + Type *VisitDependentSizedExtVectorType( const DependentSizedExtVectorType *T) { return Visit(T->getElementType()); } - AutoType *VisitVectorType(const VectorType *T) { + Type *VisitVectorType(const VectorType *T) { return Visit(T->getElementType()); } - AutoType *VisitFunctionType(const FunctionType *T) { + Type *VisitFunctionProtoType(const FunctionProtoType *T) { + if (Syntactic && T->hasTrailingReturn()) + return const_cast<FunctionProtoType*>(T); + return VisitFunctionType(T); + } + Type *VisitFunctionType(const FunctionType *T) { return Visit(T->getReturnType()); } - AutoType *VisitParenType(const ParenType *T) { + Type *VisitParenType(const ParenType *T) { return Visit(T->getInnerType()); } - AutoType *VisitAttributedType(const AttributedType *T) { + Type *VisitAttributedType(const AttributedType *T) { return Visit(T->getModifiedType()); } - AutoType *VisitAdjustedType(const AdjustedType *T) { + Type *VisitAdjustedType(const AdjustedType *T) { return Visit(T->getOriginalType()); } }; } -AutoType *Type::getContainedAutoType() const { - return GetContainedAutoVisitor().Visit(this); +DeducedType *Type::getContainedDeducedType() const { + return cast_or_null<DeducedType>( + GetContainedDeducedTypeVisitor().Visit(this)); +} + +bool Type::hasAutoForTrailingReturnType() const { + return dyn_cast_or_null<FunctionType>( + GetContainedDeducedTypeVisitor(true).Visit(this)); } bool Type::hasIntegerRepresentation() const { @@ -2005,20 +2023,8 @@ bool QualType::isCXX98PODType(const ASTContext &Context) const { if ((*this)->isIncompleteType()) return false; - if (Context.getLangOpts().ObjCAutoRefCount) { - switch (getObjCLifetime()) { - case Qualifiers::OCL_ExplicitNone: - return true; - - case Qualifiers::OCL_Strong: - case Qualifiers::OCL_Weak: - case Qualifiers::OCL_Autoreleasing: - return false; - - case Qualifiers::OCL_None: - break; - } - } + if (hasNonTrivialObjCLifetime()) + return false; QualType CanonicalType = getTypePtr()->CanonicalType; switch (CanonicalType->getTypeClass()) { @@ -2067,22 +2073,8 @@ bool QualType::isTrivialType(const ASTContext &Context) const { if ((*this)->isIncompleteType()) return false; - if (Context.getLangOpts().ObjCAutoRefCount) { - switch (getObjCLifetime()) { - case Qualifiers::OCL_ExplicitNone: - return true; - - case Qualifiers::OCL_Strong: - case Qualifiers::OCL_Weak: - case Qualifiers::OCL_Autoreleasing: - return false; - - case Qualifiers::OCL_None: - if ((*this)->isObjCLifetimeType()) - return false; - break; - } - } + if (hasNonTrivialObjCLifetime()) + return false; QualType CanonicalType = getTypePtr()->CanonicalType; if (CanonicalType->isDependentType()) @@ -2119,35 +2111,18 @@ bool QualType::isTriviallyCopyableType(const ASTContext &Context) const { if ((*this)->isArrayType()) return Context.getBaseElementType(*this).isTriviallyCopyableType(Context); - if (Context.getLangOpts().ObjCAutoRefCount) { - switch (getObjCLifetime()) { - case Qualifiers::OCL_ExplicitNone: - return true; - - case Qualifiers::OCL_Strong: - case Qualifiers::OCL_Weak: - case Qualifiers::OCL_Autoreleasing: - return false; - - case Qualifiers::OCL_None: - if ((*this)->isObjCLifetimeType()) - return false; - break; - } - } + if (hasNonTrivialObjCLifetime()) + return false; - // C++11 [basic.types]p9 + // C++11 [basic.types]p9 - See Core 2094 // Scalar types, trivially copyable class types, arrays of such types, and - // non-volatile const-qualified versions of these types are collectively + // cv-qualified versions of these types are collectively // called trivially copyable types. QualType CanonicalType = getCanonicalType(); if (CanonicalType->isDependentType()) return false; - if (CanonicalType.isVolatileQualified()) - return false; - // Return false for incomplete types after skipping any incomplete array types // which are expressly allowed by the standard and thus our API. if (CanonicalType->isIncompleteType()) @@ -2170,7 +2145,11 @@ bool QualType::isTriviallyCopyableType(const ASTContext &Context) const { return false; } - +bool QualType::isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const { + return !Context.getLangOpts().ObjCAutoRefCount && + Context.getLangOpts().ObjCWeak && + getObjCLifetime() != Qualifiers::OCL_Weak; +} bool Type::isLiteralType(const ASTContext &Ctx) const { if (isDependentType()) @@ -2280,20 +2259,8 @@ bool QualType::isCXX11PODType(const ASTContext &Context) const { if (ty->isDependentType()) return false; - if (Context.getLangOpts().ObjCAutoRefCount) { - switch (getObjCLifetime()) { - case Qualifiers::OCL_ExplicitNone: - return true; - - case Qualifiers::OCL_Strong: - case Qualifiers::OCL_Weak: - case Qualifiers::OCL_Autoreleasing: - return false; - - case Qualifiers::OCL_None: - break; - } - } + if (hasNonTrivialObjCLifetime()) + return false; // C++11 [basic.types]p9: // Scalar types, POD classes, arrays of such types, and cv-qualified @@ -2346,6 +2313,15 @@ bool Type::isAlignValT() const { return false; } +bool Type::isStdByteType() const { + if (auto *ET = getAs<EnumType>()) { + auto *II = ET->getDecl()->getIdentifier(); + if (II && II->isStr("byte") && ET->getDecl()->isInStdNamespace()) + return true; + } + return false; +} + bool Type::isPromotableIntegerType() const { if (const BuiltinType *BT = getAs<BuiltinType>()) switch (BT->getKind()) { @@ -2630,8 +2606,6 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const { return "clk_event_t"; case OCLQueue: return "queue_t"; - case OCLNDRange: - return "ndrange_t"; case OCLReserveID: return "reserve_id_t"; case OMPArraySection: @@ -2665,7 +2639,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { case CC_X86ThisCall: return "thiscall"; case CC_X86Pascal: return "pascal"; case CC_X86VectorCall: return "vectorcall"; - case CC_X86_64Win64: return "ms_abi"; + case CC_Win64: return "ms_abi"; case CC_X86_64SysV: return "sysv_abi"; case CC_X86RegCall : return "regcall"; case CC_AAPCS: return "aapcs"; @@ -3058,6 +3032,7 @@ bool AttributedType::isQualifier() const { case AttributedType::attr_sptr: case AttributedType::attr_uptr: case AttributedType::attr_objc_kindof: + case AttributedType::attr_ns_returns_retained: return false; } llvm_unreachable("bad attributed type kind"); @@ -3091,6 +3066,7 @@ bool AttributedType::isCallingConv() const { case attr_objc_inert_unsafe_unretained: case attr_noreturn: case attr_nonnull: + case attr_ns_returns_retained: case attr_nullable: case attr_null_unspecified: case attr_objc_kindof: @@ -3365,6 +3341,7 @@ static CachedProperties computeCachedProperties(const Type *T) { return CachedProperties(ExternalLinkage, false); case Type::Auto: + case Type::DeducedTemplateSpecialization: // Give non-deduced 'auto' types external linkage. We should only see them // here in error recovery. return CachedProperties(ExternalLinkage, false); @@ -3472,6 +3449,7 @@ static LinkageInfo computeLinkageInfo(const Type *T) { return LinkageInfo::external(); case Type::Auto: + case Type::DeducedTemplateSpecialization: return LinkageInfo::external(); case Type::Record: @@ -3564,7 +3542,7 @@ Optional<NullabilityKind> Type::getNullability(const ASTContext &context) const } while (true); } -bool Type::canHaveNullability() const { +bool Type::canHaveNullability(bool ResultIfUnknown) const { QualType type = getCanonicalTypeInternal(); switch (type->getTypeClass()) { @@ -3592,7 +3570,8 @@ bool Type::canHaveNullability() const { case Type::SubstTemplateTypeParmPack: case Type::DependentName: case Type::DependentTemplateSpecialization: - return true; + case Type::Auto: + return ResultIfUnknown; // Dependent template specializations can instantiate to pointer // types unless they're known to be specializations of a class @@ -3604,11 +3583,7 @@ bool Type::canHaveNullability() const { if (isa<ClassTemplateDecl>(templateDecl)) return false; } - return true; - - // auto is considered dependent when it isn't deduced. - case Type::Auto: - return !cast<AutoType>(type.getTypePtr())->isDeduced(); + return ResultIfUnknown; case Type::Builtin: switch (cast<BuiltinType>(type.getTypePtr())->getKind()) { @@ -3627,7 +3602,7 @@ bool Type::canHaveNullability() const { case BuiltinType::PseudoObject: case BuiltinType::UnknownAny: case BuiltinType::ARCUnbridgedCast: - return true; + return ResultIfUnknown; case BuiltinType::Void: case BuiltinType::ObjCId: @@ -3640,13 +3615,13 @@ bool Type::canHaveNullability() const { case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: case BuiltinType::OCLQueue: - case BuiltinType::OCLNDRange: case BuiltinType::OCLReserveID: case BuiltinType::BuiltinFn: case BuiltinType::NullPtr: case BuiltinType::OMPArraySection: return false; } + llvm_unreachable("unknown builtin type"); // Non-pointer types. case Type::Complex: @@ -3662,6 +3637,7 @@ bool Type::canHaveNullability() const { case Type::FunctionProto: case Type::FunctionNoProto: case Type::Record: + case Type::DeducedTemplateSpecialization: case Type::Enum: case Type::InjectedClassName: case Type::PackExpansion: diff --git a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp index 7242858..c9a2686 100644 --- a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp @@ -340,7 +340,6 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: case BuiltinType::OCLQueue: - case BuiltinType::OCLNDRange: case BuiltinType::OCLReserveID: case BuiltinType::BuiltinFn: case BuiltinType::OMPArraySection: diff --git a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp index cccc908..15c63bf 100644 --- a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp @@ -96,7 +96,7 @@ namespace { static bool canPrefixQualifiers(const Type *T, bool &NeedARCStrongQualifier); void spaceBeforePlaceHolder(raw_ostream &OS); - void printTypeSpec(const NamedDecl *D, raw_ostream &OS); + void printTypeSpec(NamedDecl *D, raw_ostream &OS); void printBefore(const Type *ty, Qualifiers qs, raw_ostream &OS); void printBefore(QualType T, raw_ostream &OS); @@ -104,6 +104,7 @@ namespace { void printAfter(QualType T, raw_ostream &OS); void AppendScope(DeclContext *DC, raw_ostream &OS); void printTag(TagDecl *T, raw_ostream &OS); + void printFunctionAfter(const FunctionType::ExtInfo &Info, raw_ostream &OS); #define ABSTRACT_TYPE(CLASS, PARENT) #define TYPE(CLASS, PARENT) \ void print##CLASS##Before(const CLASS##Type *T, raw_ostream &OS); \ @@ -189,6 +190,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::Elaborated: case Type::TemplateTypeParm: case Type::SubstTemplateTypeParmPack: + case Type::DeducedTemplateSpecialization: case Type::TemplateSpecialization: case Type::InjectedClassName: case Type::DependentName: @@ -684,6 +686,36 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, FunctionType::ExtInfo Info = T->getExtInfo(); + printFunctionAfter(Info, OS); + + if (unsigned quals = T->getTypeQuals()) { + OS << ' '; + AppendTypeQualList(OS, quals, Policy.Restrict); + } + + switch (T->getRefQualifier()) { + case RQ_None: + break; + + case RQ_LValue: + OS << " &"; + break; + + case RQ_RValue: + OS << " &&"; + break; + } + T->printExceptionSpecification(OS, Policy); + + if (T->hasTrailingReturn()) { + OS << " -> "; + print(T->getReturnType(), OS, StringRef()); + } else + printAfter(T->getReturnType(), OS); +} + +void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info, + raw_ostream &OS) { if (!InsideCCAttribute) { switch (Info.getCC()) { case CC_C: @@ -719,7 +751,7 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, case CC_IntelOclBicc: OS << " __attribute__((intel_ocl_bicc))"; break; - case CC_X86_64Win64: + case CC_Win64: OS << " __attribute__((ms_abi))"; break; case CC_X86_64SysV: @@ -746,34 +778,13 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, if (Info.getNoReturn()) OS << " __attribute__((noreturn))"; + if (Info.getProducesResult()) + OS << " __attribute__((ns_returns_retained))"; if (Info.getRegParm()) OS << " __attribute__((regparm (" << Info.getRegParm() << ")))"; - - if (unsigned quals = T->getTypeQuals()) { - OS << ' '; - AppendTypeQualList(OS, quals, Policy.Restrict); - } - - switch (T->getRefQualifier()) { - case RQ_None: - break; - - case RQ_LValue: - OS << " &"; - break; - - case RQ_RValue: - OS << " &&"; - break; - } - T->printExceptionSpecification(OS, Policy); - - if (T->hasTrailingReturn()) { - OS << " -> "; - print(T->getReturnType(), OS, StringRef()); - } else - printAfter(T->getReturnType(), OS); + if (Info.getNoCallerSavedRegs()) + OS << " __attribute__((no_caller_saved_registers))"; } void TypePrinter::printFunctionNoProtoBefore(const FunctionNoProtoType *T, @@ -792,12 +803,18 @@ void TypePrinter::printFunctionNoProtoAfter(const FunctionNoProtoType *T, SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); OS << "()"; - if (T->getNoReturnAttr()) - OS << " __attribute__((noreturn))"; + printFunctionAfter(T->getExtInfo(), OS); printAfter(T->getReturnType(), OS); } -void TypePrinter::printTypeSpec(const NamedDecl *D, raw_ostream &OS) { +void TypePrinter::printTypeSpec(NamedDecl *D, raw_ostream &OS) { + + // Compute the full nested-name-specifier for this type. + // In C, this will always be empty except when the type + // being printed is anonymous within other Record. + if (!Policy.SuppressScope) + AppendScope(D->getDeclContext(), OS); + IdentifierInfo *II = D->getIdentifier(); OS << II->getName(); spaceBeforePlaceHolder(OS); @@ -888,6 +905,24 @@ void TypePrinter::printAutoAfter(const AutoType *T, raw_ostream &OS) { printAfter(T->getDeducedType(), OS); } +void TypePrinter::printDeducedTemplateSpecializationBefore( + const DeducedTemplateSpecializationType *T, raw_ostream &OS) { + // If the type has been deduced, print the deduced type. + if (!T->getDeducedType().isNull()) { + printBefore(T->getDeducedType(), OS); + } else { + IncludeStrongLifetimeRAII Strong(Policy); + T->getTemplateName().print(OS, Policy); + spaceBeforePlaceHolder(OS); + } +} +void TypePrinter::printDeducedTemplateSpecializationAfter( + const DeducedTemplateSpecializationType *T, raw_ostream &OS) { + // If the type has been deduced, print the deduced type. + if (!T->getDeducedType().isNull()) + printAfter(T->getDeducedType(), OS); +} + void TypePrinter::printAtomicBefore(const AtomicType *T, raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); @@ -1242,6 +1277,12 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, if (T->getAttrKind() == AttributedType::attr_objc_inert_unsafe_unretained) return; + // Don't print ns_returns_retained unless it had an effect. + if (T->getAttrKind() == AttributedType::attr_ns_returns_retained && + !T->getEquivalentType()->castAs<FunctionType>() + ->getExtInfo().getProducesResult()) + return; + // Print nullability type specifiers that occur after if (T->getAttrKind() == AttributedType::attr_nonnull || T->getAttrKind() == AttributedType::attr_nullable || @@ -1333,6 +1374,10 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, OS << ')'; break; + case AttributedType::attr_ns_returns_retained: + OS << "ns_returns_retained"; + break; + // FIXME: When Sema learns to form this AttributedType, avoid printing the // attribute again in printFunctionProtoAfter. case AttributedType::attr_noreturn: OS << "noreturn"; break; @@ -1627,14 +1672,22 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy, OS << "__local"; break; case LangAS::opencl_constant: + case LangAS::cuda_constant: OS << "__constant"; break; case LangAS::opencl_generic: OS << "__generic"; break; + case LangAS::cuda_device: + OS << "__device"; + break; + case LangAS::cuda_shared: + OS << "__shared"; + break; default: + assert(addrspace >= LangAS::FirstTargetAddressSpace); OS << "__attribute__((address_space("; - OS << addrspace; + OS << addrspace - LangAS::FirstTargetAddressSpace; OS << ")))"; } } |