diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:11:37 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:11:37 +0000 |
commit | 461a67fa15370a9ec88f8f8a240bf7c123bb2029 (patch) | |
tree | 6942083d7d56bba40ec790a453ca58ad3baf6832 /lib | |
parent | 75c3240472ba6ac2669ee72ca67eb72d4e2851fc (diff) | |
download | src-461a67fa15370a9ec88f8f8a240bf7c123bb2029.tar.gz src-461a67fa15370a9ec88f8f8a240bf7c123bb2029.zip |
Vendor import of clang trunk r321017:vendor/clang/clang-trunk-r321017
Notes
Notes:
svn path=/vendor/clang/dist/; revision=326941
svn path=/vendor/clang/clang-trunk-r321017/; revision=326942; tag=vendor/clang/clang-trunk-r321017
Diffstat (limited to 'lib')
486 files changed, 47816 insertions, 26475 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index c60373c5a90a..dd96148edb27 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1,4 +1,4 @@ -//===--- ASTContext.cpp - Context to hold long-lived AST nodes ------------===// +//===- ASTContext.cpp - Context to hold long-lived AST nodes --------------===// // // The LLVM Compiler Infrastructure // @@ -13,33 +13,83 @@ #include "clang/AST/ASTContext.h" #include "CXXABI.h" +#include "clang/AST/APValue.h" #include "clang/AST/ASTMutationListener.h" +#include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Attr.h" +#include "clang/AST/AttrIterator.h" #include "clang/AST/CharUnits.h" #include "clang/AST/Comment.h" -#include "clang/AST/CommentCommandTraits.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclContextInternals.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/Mangle.h" #include "clang/AST/MangleNumberingContext.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/RawCommentList.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/TemplateName.h" +#include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" +#include "clang/AST/UnresolvedSet.h" #include "clang/AST/VTableBuilder.h" +#include "clang/Basic/AddressSpaces.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/CommentOptions.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/Linkage.h" +#include "clang/Basic/ObjCRuntime.h" +#include "clang/Basic/SanitizerBlacklist.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/Specifiers.h" +#include "clang/Basic/TargetCXXABI.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Basic/XRayLists.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/Capacity.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <cstdlib> #include <map> +#include <memory> +#include <string> +#include <tuple> +#include <utility> using namespace clang; @@ -57,7 +107,7 @@ unsigned ASTContext::NumImplicitDestructors; unsigned ASTContext::NumImplicitDestructorsDeclared; enum FloatingRank { - HalfRank, FloatRank, DoubleRank, LongDoubleRank, Float128Rank + Float16Rank, HalfRank, FloatRank, DoubleRank, LongDoubleRank, Float128Rank }; RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { @@ -256,11 +306,10 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { return *Comment; } -namespace { /// If we have a 'templated' declaration for a template, adjust 'D' to /// refer to the actual template. /// If we have an implicit instantiation, adjust 'D' to refer to template. -const Decl *adjustDeclToTemplate(const Decl *D) { +static const Decl *adjustDeclToTemplate(const Decl *D) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { // Is this function declaration part of a function template? if (const FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate()) @@ -327,7 +376,6 @@ const Decl *adjustDeclToTemplate(const Decl *D) { // FIXME: Adjust alias templates? return D; } -} // anonymous namespace const RawComment *ASTContext::getRawCommentForAnyRedecl( const Decl *D, @@ -697,8 +745,8 @@ CXXABI *ASTContext::createCXXABI(const TargetInfo &T) { llvm_unreachable("Invalid CXXABI type!"); } -static const LangAS::Map *getAddressSpaceMap(const TargetInfo &T, - const LangOptions &LOpts) { +static const LangASMap *getAddressSpaceMap(const TargetInfo &T, + const LangOptions &LOpts) { if (LOpts.FakeAddressSpaceMap) { // The fake address space map must have a distinct entry for each // language-specific address space. @@ -707,6 +755,7 @@ static const LangAS::Map *getAddressSpaceMap(const TargetInfo &T, 1, // opencl_global 3, // opencl_local 2, // opencl_constant + 0, // opencl_private 4, // opencl_generic 5, // cuda_device 6, // cuda_constant @@ -736,25 +785,12 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, Builtin::Context &builtins) : FunctionProtoTypes(this_()), TemplateSpecializationTypes(this_()), DependentTemplateSpecializationTypes(this_()), - SubstTemplateTemplateParmPacks(this_()), - GlobalNestedNameSpecifier(nullptr), Int128Decl(nullptr), - UInt128Decl(nullptr), BuiltinVaListDecl(nullptr), - BuiltinMSVaListDecl(nullptr), ObjCIdDecl(nullptr), ObjCSelDecl(nullptr), - ObjCClassDecl(nullptr), ObjCProtocolClassDecl(nullptr), BOOLDecl(nullptr), - CFConstantStringTagDecl(nullptr), CFConstantStringTypeDecl(nullptr), - ObjCInstanceTypeDecl(nullptr), FILEDecl(nullptr), jmp_bufDecl(nullptr), - sigjmp_bufDecl(nullptr), ucontext_tDecl(nullptr), - BlockDescriptorType(nullptr), BlockDescriptorExtendedType(nullptr), - cudaConfigureCallDecl(nullptr), FirstLocalImport(), LastLocalImport(), - ExternCContext(nullptr), MakeIntegerSeqDecl(nullptr), - TypePackElementDecl(nullptr), SourceMgr(SM), LangOpts(LOpts), + SubstTemplateTemplateParmPacks(this_()), 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), - Listener(nullptr), Comments(SM), CommentsLoaded(false), + BuiltinInfo(builtins), DeclarationNames(*this), Comments(SM), CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), LastSDM(nullptr, 0) { TUDecl = TranslationUnitDecl::Create(*this); } @@ -1093,6 +1129,9 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target, // GNU extension, __float128 for IEEE quadruple precision InitBuiltinType(Float128Ty, BuiltinType::Float128); + // C11 extension ISO/IEC TS 18661-3 + InitBuiltinType(Float16Ty, BuiltinType::Float16); + // GNU extension, 128-bit integers. InitBuiltinType(Int128Ty, BuiltinType::Int128); InitBuiltinType(UnsignedInt128Ty, BuiltinType::UInt128); @@ -1182,7 +1221,14 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target, ObjCSuperType = QualType(); // void * type - VoidPtrTy = getPointerType(VoidTy); + if (LangOpts.OpenCLVersion >= 200) { + auto Q = VoidTy.getQualifiers(); + Q.setAddressSpace(LangAS::opencl_generic); + VoidPtrTy = getPointerType(getCanonicalType( + getQualifiedType(VoidTy.getUnqualifiedType(), Q))); + } else { + VoidPtrTy = getPointerType(VoidTy); + } // nullptr type (C++0x 2.14.7) InitBuiltinType(NullPtrTy, BuiltinType::NullPtr); @@ -1209,7 +1255,7 @@ AttrVec& ASTContext::getDeclAttrs(const Decl *D) { } /// \brief Erase the attributes corresponding to the given declaration. -void ASTContext::eraseDeclAttrs(const Decl *D) { +void ASTContext::eraseDeclAttrs(const Decl *D) { llvm::DenseMap<const Decl*, AttrVec*>::iterator Pos = DeclAttrs.find(D); if (Pos != DeclAttrs.end()) { Pos->second->~AttrVec(); @@ -1332,35 +1378,27 @@ void ASTContext::setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, ASTContext::overridden_cxx_method_iterator ASTContext::overridden_methods_begin(const CXXMethodDecl *Method) const { - llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos = - OverriddenMethods.find(Method->getCanonicalDecl()); - if (Pos == OverriddenMethods.end()) - return nullptr; - return Pos->second.begin(); + return overridden_methods(Method).begin(); } ASTContext::overridden_cxx_method_iterator ASTContext::overridden_methods_end(const CXXMethodDecl *Method) const { - llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos = - OverriddenMethods.find(Method->getCanonicalDecl()); - if (Pos == OverriddenMethods.end()) - return nullptr; - return Pos->second.end(); + return overridden_methods(Method).end(); } unsigned ASTContext::overridden_methods_size(const CXXMethodDecl *Method) const { - llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos = - OverriddenMethods.find(Method->getCanonicalDecl()); - if (Pos == OverriddenMethods.end()) - return 0; - return Pos->second.size(); + auto Range = overridden_methods(Method); + return Range.end() - Range.begin(); } ASTContext::overridden_method_range ASTContext::overridden_methods(const CXXMethodDecl *Method) const { - return overridden_method_range(overridden_methods_begin(Method), - overridden_methods_end(Method)); + llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos = + OverriddenMethods.find(Method->getCanonicalDecl()); + if (Pos == OverriddenMethods.end()) + return overridden_method_range(nullptr, nullptr); + return overridden_method_range(Pos->second.begin(), Pos->second.end()); } void ASTContext::addOverriddenMethod(const CXXMethodDecl *Method, @@ -1413,7 +1451,9 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const { assert(BT && "Not a floating point type!"); switch (BT->getKind()) { default: llvm_unreachable("Not a floating point type!"); - case BuiltinType::Half: return Target->getHalfFormat(); + case BuiltinType::Float16: + case BuiltinType::Half: + return Target->getHalfFormat(); case BuiltinType::Float: return Target->getFloatFormat(); case BuiltinType::Double: return Target->getDoubleFormat(); case BuiltinType::LongDouble: return Target->getLongDoubleFormat(); @@ -1450,7 +1490,6 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const { // else about the declaration and its type. if (UseAlignAttrOnly) { // do nothing - } else if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) { QualType T = VD->getType(); if (const ReferenceType *RT = T->getAs<ReferenceType>()) { @@ -1624,6 +1663,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { uint64_t Width = 0; unsigned Align = 8; bool AlignIsRequired = false; + unsigned AS = 0; switch (T->getTypeClass()) { #define TYPE(Class, Base) #define ABSTRACT_TYPE(Class, Base) @@ -1690,7 +1730,6 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Width = 0; Align = 8; break; - case BuiltinType::Bool: Width = Target->getBoolWidth(); Align = Target->getBoolAlign(); @@ -1740,6 +1779,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Width = 128; Align = 128; // int128_t is 128-bit aligned on all targets. break; + case BuiltinType::Float16: case BuiltinType::Half: Width = Target->getHalfWidth(); Align = Target->getHalfAlign(); @@ -1770,60 +1810,48 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Width = Target->getPointerWidth(0); Align = Target->getPointerAlign(0); break; - case BuiltinType::OCLSampler: { - auto AS = getTargetAddressSpace(LangAS::opencl_constant); - Width = Target->getPointerWidth(AS); - Align = Target->getPointerAlign(AS); - break; - } + case BuiltinType::OCLSampler: case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: case BuiltinType::OCLQueue: case BuiltinType::OCLReserveID: - // Currently these types are pointers to opaque types. - Width = Target->getPointerWidth(0); - Align = Target->getPointerAlign(0); - break; #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ case BuiltinType::Id: #include "clang/Basic/OpenCLImageTypes.def" - { - auto AS = getTargetAddressSpace(Target->getOpenCLImageAddrSpace()); - Width = Target->getPointerWidth(AS); - Align = Target->getPointerAlign(AS); - } + AS = getTargetAddressSpace( + Target->getOpenCLTypeAddrSpace(getOpenCLTypeKind(T))); + Width = Target->getPointerWidth(AS); + Align = Target->getPointerAlign(AS); + break; } break; case Type::ObjCObjectPointer: Width = Target->getPointerWidth(0); Align = Target->getPointerAlign(0); break; - case Type::BlockPointer: { - unsigned AS = getTargetAddressSpace( - cast<BlockPointerType>(T)->getPointeeType()); + case Type::BlockPointer: + AS = getTargetAddressSpace(cast<BlockPointerType>(T)->getPointeeType()); Width = Target->getPointerWidth(AS); Align = Target->getPointerAlign(AS); break; - } case Type::LValueReference: - case Type::RValueReference: { + case Type::RValueReference: // alignof and sizeof should never enter this code path here, so we go // the pointer route. - unsigned AS = getTargetAddressSpace( - cast<ReferenceType>(T)->getPointeeType()); + AS = getTargetAddressSpace(cast<ReferenceType>(T)->getPointeeType()); Width = Target->getPointerWidth(AS); Align = Target->getPointerAlign(AS); break; - } - case Type::Pointer: { - unsigned AS = getTargetAddressSpace(cast<PointerType>(T)->getPointeeType()); + case Type::Pointer: + AS = getTargetAddressSpace(cast<PointerType>(T)->getPointeeType()); Width = Target->getPointerWidth(AS); Align = Target->getPointerAlign(AS); break; - } case Type::MemberPointer: { const MemberPointerType *MPT = cast<MemberPointerType>(T); - std::tie(Width, Align) = ABI->getMemberPointerWidthAndAlign(MPT); + CXXABI::MemberPointerInfo MPI = ABI->getMemberPointerInfo(MPT); + Width = MPI.Width; + Align = MPI.Align; break; } case Type::Complex: { @@ -1938,11 +1966,10 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { } break; - case Type::Pipe: { + case Type::Pipe: Width = Target->getPointerWidth(getTargetAddressSpace(LangAS::opencl_global)); Align = Target->getPointerAlign(getTargetAddressSpace(LangAS::opencl_global)); - } - + break; } assert(llvm::isPowerOf2_32(Align) && "Alignment must be power of 2"); @@ -2055,7 +2082,6 @@ CharUnits ASTContext::getOffsetOfBaseWithVBPtr(const CXXRecordDecl *RD) const { /// super class and then collects all ivars, including those synthesized for /// current class. This routine is used for implementation of current class /// when all ivars, declared and synthesized are known. -/// void ASTContext::DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass, SmallVectorImpl<const ObjCIvarDecl*> &Ivars) const { @@ -2107,6 +2133,171 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl, } } +static bool unionHasUniqueObjectRepresentations(const ASTContext &Context, + const RecordDecl *RD) { + assert(RD->isUnion() && "Must be union type"); + CharUnits UnionSize = Context.getTypeSizeInChars(RD->getTypeForDecl()); + + for (const auto *Field : RD->fields()) { + if (!Context.hasUniqueObjectRepresentations(Field->getType())) + return false; + CharUnits FieldSize = Context.getTypeSizeInChars(Field->getType()); + if (FieldSize != UnionSize) + return false; + } + return true; +} + +bool isStructEmpty(QualType Ty) { + const RecordDecl *RD = Ty->castAs<RecordType>()->getDecl(); + + if (!RD->field_empty()) + return false; + + if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RD)) + return ClassDecl->isEmpty(); + + return true; +} + +static llvm::Optional<int64_t> +structHasUniqueObjectRepresentations(const ASTContext &Context, + const RecordDecl *RD) { + assert(!RD->isUnion() && "Must be struct/class type"); + const auto &Layout = Context.getASTRecordLayout(RD); + + int64_t CurOffsetInBits = 0; + if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RD)) { + if (ClassDecl->isDynamicClass()) + return llvm::None; + + SmallVector<std::pair<QualType, int64_t>, 4> Bases; + for (const auto Base : ClassDecl->bases()) { + // Empty types can be inherited from, and non-empty types can potentially + // have tail padding, so just make sure there isn't an error. + if (!isStructEmpty(Base.getType())) { + llvm::Optional<int64_t> Size = structHasUniqueObjectRepresentations( + Context, Base.getType()->getAs<RecordType>()->getDecl()); + if (!Size) + return llvm::None; + Bases.emplace_back(Base.getType(), Size.getValue()); + } + } + + std::sort( + Bases.begin(), Bases.end(), [&](const std::pair<QualType, int64_t> &L, + const std::pair<QualType, int64_t> &R) { + return Layout.getBaseClassOffset(L.first->getAsCXXRecordDecl()) < + Layout.getBaseClassOffset(R.first->getAsCXXRecordDecl()); + }); + + for (const auto Base : Bases) { + int64_t BaseOffset = Context.toBits( + Layout.getBaseClassOffset(Base.first->getAsCXXRecordDecl())); + int64_t BaseSize = Base.second; + if (BaseOffset != CurOffsetInBits) + return llvm::None; + CurOffsetInBits = BaseOffset + BaseSize; + } + } + + for (const auto *Field : RD->fields()) { + if (!Field->getType()->isReferenceType() && + !Context.hasUniqueObjectRepresentations(Field->getType())) + return llvm::None; + + int64_t FieldSizeInBits = + Context.toBits(Context.getTypeSizeInChars(Field->getType())); + if (Field->isBitField()) { + int64_t BitfieldSize = Field->getBitWidthValue(Context); + + if (BitfieldSize > FieldSizeInBits) + return llvm::None; + FieldSizeInBits = BitfieldSize; + } + + int64_t FieldOffsetInBits = Context.getFieldOffset(Field); + + if (FieldOffsetInBits != CurOffsetInBits) + return llvm::None; + + CurOffsetInBits = FieldSizeInBits + FieldOffsetInBits; + } + + return CurOffsetInBits; +} + +bool ASTContext::hasUniqueObjectRepresentations(QualType Ty) const { + // C++17 [meta.unary.prop]: + // The predicate condition for a template specialization + // has_unique_object_representations<T> shall be + // satisfied if and only if: + // (9.1) - T is trivially copyable, and + // (9.2) - any two objects of type T with the same value have the same + // object representation, where two objects + // of array or non-union class type are considered to have the same value + // if their respective sequences of + // direct subobjects have the same values, and two objects of union type + // are considered to have the same + // value if they have the same active member and the corresponding members + // have the same value. + // The set of scalar types for which this condition holds is + // implementation-defined. [ Note: If a type has padding + // bits, the condition does not hold; otherwise, the condition holds true + // for unsigned integral types. -- end note ] + assert(!Ty.isNull() && "Null QualType sent to unique object rep check"); + + // Arrays are unique only if their element type is unique. + if (Ty->isArrayType()) + return hasUniqueObjectRepresentations(getBaseElementType(Ty)); + + // (9.1) - T is trivially copyable... + if (!Ty.isTriviallyCopyableType(*this)) + return false; + + // All integrals and enums are unique. + if (Ty->isIntegralOrEnumerationType()) + return true; + + // All other pointers are unique. + if (Ty->isPointerType()) + return true; + + if (Ty->isMemberPointerType()) { + const MemberPointerType *MPT = Ty->getAs<MemberPointerType>(); + return !ABI->getMemberPointerInfo(MPT).HasPadding; + } + + if (Ty->isRecordType()) { + const RecordDecl *Record = Ty->getAs<RecordType>()->getDecl(); + + if (Record->isInvalidDecl()) + return false; + + if (Record->isUnion()) + return unionHasUniqueObjectRepresentations(*this, Record); + + Optional<int64_t> StructSize = + structHasUniqueObjectRepresentations(*this, Record); + + return StructSize && + StructSize.getValue() == static_cast<int64_t>(getTypeSize(Ty)); + } + + // FIXME: More cases to handle here (list by rsmith): + // vectors (careful about, eg, vector of 3 foo) + // _Complex int and friends + // _Atomic T + // Obj-C block pointers + // Obj-C object pointers + // and perhaps OpenCL's various builtin types (pipe, sampler_t, event_t, + // clk_event_t, queue_t, reserve_id_t) + // There're also Obj-C class types and the Obj-C selector type, but I think it + // makes sense for those to return false here. + + return false; +} + unsigned ASTContext::CountNonClassIvars(const ObjCInterfaceDecl *OI) const { unsigned count = 0; // Count ivars declared in class extension. @@ -2139,7 +2330,8 @@ bool ASTContext::isSentinelNullExpr(const Expr *E) { return false; } -/// \brief Get the implementation of ObjCInterfaceDecl,or NULL if none exists. +/// \brief Get the implementation of ObjCInterfaceDecl, or nullptr if none +/// exists. ObjCImplementationDecl *ASTContext::getObjCImplementation(ObjCInterfaceDecl *D) { llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*>::iterator I = ObjCImpls.find(D); @@ -2147,7 +2339,9 @@ ObjCImplementationDecl *ASTContext::getObjCImplementation(ObjCInterfaceDecl *D) return cast<ObjCImplementationDecl>(I->second); return nullptr; } -/// \brief Get the implementation of ObjCCategoryDecl, or NULL if none exists. + +/// \brief Get the implementation of ObjCCategoryDecl, or nullptr if none +/// exists. ObjCCategoryImplDecl *ASTContext::getObjCImplementation(ObjCCategoryDecl *D) { llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*>::iterator I = ObjCImpls.find(D); @@ -2162,6 +2356,7 @@ void ASTContext::setObjCImplementation(ObjCInterfaceDecl *IFaceD, assert(IFaceD && ImplD && "Passed null params"); ObjCImpls[IFaceD] = ImplD; } + /// \brief Set the implementation of ObjCCategoryDecl. void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD, ObjCCategoryImplDecl *ImplD) { @@ -2195,7 +2390,7 @@ const ObjCInterfaceDecl *ASTContext::getObjContainingInterface( return nullptr; } -/// \brief Get the copy initialization expression of VarDecl,or NULL if +/// \brief Get the copy initialization expression of VarDecl, or nullptr if /// none exists. Expr *ASTContext::getBlockVarCopyInits(const VarDecl*VD) { assert(VD && "Passed null params"); @@ -2280,8 +2475,8 @@ ASTContext::getExtQualType(const Type *baseType, Qualifiers quals) const { return QualType(eq, fastQuals); } -QualType -ASTContext::getAddrSpaceQualType(QualType T, unsigned AddressSpace) const { +QualType ASTContext::getAddrSpaceQualType(QualType T, + LangAS AddressSpace) const { QualType CanT = getCanonicalType(T); if (CanT.getAddressSpace() == AddressSpace) return T; @@ -2300,6 +2495,27 @@ ASTContext::getAddrSpaceQualType(QualType T, unsigned AddressSpace) const { return getExtQualType(TypeNode, Quals); } +QualType ASTContext::removeAddrSpaceQualType(QualType T) const { + // If we are composing extended qualifiers together, merge together + // into one ExtQuals node. + QualifierCollector Quals; + const Type *TypeNode = Quals.strip(T); + + // If the qualifier doesn't have an address space just return it. + if (!Quals.hasAddressSpace()) + return T; + + Quals.removeAddressSpace(); + + // Removal of the address space can mean there are no longer any + // non-fast qualifiers, so creating an ExtQualType isn't possible (asserts) + // or required. + if (Quals.hasNonFastQualifiers()) + return getExtQualType(TypeNode, Quals); + else + return QualType(TypeNode, Quals.getFastQualifiers()); +} + QualType ASTContext::getObjCGCQualType(QualType T, Qualifiers::GC GCAttr) const { QualType CanT = getCanonicalType(T); @@ -2393,7 +2609,7 @@ static QualType getFunctionTypeWithExceptionSpec( bool ASTContext::hasSameFunctionTypeIgnoringExceptionSpec(QualType T, QualType U) { return hasSameType(T, U) || - (getLangOpts().CPlusPlus1z && + (getLangOpts().CPlusPlus17 && hasSameType(getFunctionTypeWithExceptionSpec(*this, T, EST_None), getFunctionTypeWithExceptionSpec(*this, U, EST_None))); } @@ -2750,6 +2966,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { case Type::Vector: case Type::ExtVector: case Type::DependentSizedExtVector: + case Type::DependentAddressSpace: case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: @@ -3098,6 +3315,41 @@ ASTContext::getDependentSizedExtVectorType(QualType vecType, return QualType(New, 0); } +QualType ASTContext::getDependentAddressSpaceType(QualType PointeeType, + Expr *AddrSpaceExpr, + SourceLocation AttrLoc) const { + assert(AddrSpaceExpr->isInstantiationDependent()); + + QualType canonPointeeType = getCanonicalType(PointeeType); + + void *insertPos = nullptr; + llvm::FoldingSetNodeID ID; + DependentAddressSpaceType::Profile(ID, *this, canonPointeeType, + AddrSpaceExpr); + + DependentAddressSpaceType *canonTy = + DependentAddressSpaceTypes.FindNodeOrInsertPos(ID, insertPos); + + if (!canonTy) { + canonTy = new (*this, TypeAlignment) + DependentAddressSpaceType(*this, canonPointeeType, + QualType(), AddrSpaceExpr, AttrLoc); + DependentAddressSpaceTypes.InsertNode(canonTy, insertPos); + Types.push_back(canonTy); + } + + if (canonPointeeType == PointeeType && + canonTy->getAddrSpaceExpr() == AddrSpaceExpr) + return QualType(canonTy, 0); + + DependentAddressSpaceType *sugaredType + = new (*this, TypeAlignment) + DependentAddressSpaceType(*this, PointeeType, QualType(canonTy, 0), + AddrSpaceExpr, AttrLoc); + Types.push_back(sugaredType); + return QualType(sugaredType, 0); +} + /// \brief Determine whether \p T is canonical as the result type of a function. static bool isCanonicalResultType(QualType T) { return T.isCanonical() && @@ -3106,7 +3358,6 @@ static bool isCanonicalResultType(QualType T) { } /// getFunctionNoProtoType - Return a K&R style C function type like 'int()'. -/// QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, const FunctionType::ExtInfo &Info) const { @@ -3222,7 +3473,7 @@ QualType ASTContext::getFunctionTypeInternal( Unique = true; } - bool NoexceptInType = getLangOpts().CPlusPlus1z; + bool NoexceptInType = getLangOpts().CPlusPlus17; bool IsCanonicalExceptionSpec = isCanonicalExceptionSpecification(EPI.ExceptionSpec, NoexceptInType); @@ -3358,7 +3609,7 @@ QualType ASTContext::getPipeType(QualType T, bool ReadOnly) const { llvm::FoldingSetNodeID ID; PipeType::Profile(ID, T, ReadOnly); - void *InsertPos = 0; + void *InsertPos = nullptr; if (PipeType *PT = PipeTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(PT, 0); @@ -3986,7 +4237,7 @@ SortAndUniqueProtocols(SmallVectorImpl<ObjCProtocolDecl *> &Protocols) { QualType ASTContext::getObjCObjectType(QualType BaseType, ObjCProtocolDecl * const *Protocols, unsigned NumProtocols) const { - return getObjCObjectType(BaseType, { }, + return getObjCObjectType(BaseType, {}, llvm::makeArrayRef(Protocols, NumProtocols), /*isKindOf=*/false); } @@ -4123,13 +4374,13 @@ ASTContext::applyObjCProtocolQualifiers(QualType type, // FIXME: Check for protocols to which the class type is already // known to conform. - return getObjCObjectType(type, { }, protocols, false); + return getObjCObjectType(type, {}, protocols, false); } // id<protocol-list> if (type->isObjCIdType()) { const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>(); - type = getObjCObjectType(ObjCBuiltinIdTy, { }, protocols, + type = getObjCObjectType(ObjCBuiltinIdTy, {}, protocols, objPtr->isKindOfType()); return getObjCObjectPointerType(type); } @@ -4137,7 +4388,7 @@ ASTContext::applyObjCProtocolQualifiers(QualType type, // Class<protocol-list> if (type->isObjCClassType()) { const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>(); - type = getObjCObjectType(ObjCBuiltinClassTy, { }, protocols, + type = getObjCObjectType(ObjCBuiltinClassTy, {}, protocols, objPtr->isKindOfType()); return getObjCObjectPointerType(type); } @@ -4512,7 +4763,7 @@ QualType ASTContext::getAutoRRefDeductType() const { /// getTagDeclType - Return the unique reference to the type for the /// specified TagDecl (struct/union/class/enum) decl. QualType ASTContext::getTagDeclType(const TagDecl *Decl) const { - assert (Decl); + assert(Decl); // FIXME: What is the design on getTagDeclType when it requires casting // away const? mutable? return getTypeDeclType(const_cast<TagDecl*>(Decl)); @@ -4569,6 +4820,13 @@ QualType ASTContext::getPointerDiffType() const { return getFromTargetType(Target->getPtrDiffType(0)); } +/// \brief Return the unique unsigned counterpart of "ptrdiff_t" +/// integer type. The standard (C11 7.21.6.1p7) refers to this type +/// in the definition of %tu format specifier. +QualType ASTContext::getUnsignedPointerDiffType() const { + return getFromTargetType(Target->getUnsignedPtrDiffType(0)); +} + /// \brief Return the unique type for "pid_t" defined in /// <sys/types.h>. We need this to compute the correct type for vfork(). QualType ASTContext::getProcessIDType() const { @@ -5051,6 +5309,7 @@ static FloatingRank getFloatingRank(QualType T) { assert(T->getAs<BuiltinType>() && "getFloatingRank(): not a floating type"); switch (T->getAs<BuiltinType>()->getKind()) { default: llvm_unreachable("getFloatingRank(): not a floating type"); + case BuiltinType::Float16: return Float16Rank; case BuiltinType::Half: return HalfRank; case BuiltinType::Float: return FloatRank; case BuiltinType::Double: return DoubleRank; @@ -5068,6 +5327,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size, FloatingRank EltRank = getFloatingRank(Size); if (Domain->isComplexType()) { switch (EltRank) { + case Float16Rank: case HalfRank: llvm_unreachable("Complex half is not supported"); case FloatRank: return FloatComplexTy; case DoubleRank: return DoubleComplexTy; @@ -5078,6 +5338,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size, assert(Domain->isRealFloatingType() && "Unknown domain!"); switch (EltRank) { + case Float16Rank: return HalfTy; case HalfRank: return HalfTy; case FloatRank: return FloatTy; case DoubleRank: return DoubleTy; @@ -5455,6 +5716,46 @@ QualType ASTContext::getBlockDescriptorExtendedType() const { return getTagDeclType(BlockDescriptorExtendedType); } +TargetInfo::OpenCLTypeKind ASTContext::getOpenCLTypeKind(const Type *T) const { + auto BT = dyn_cast<BuiltinType>(T); + + if (!BT) { + if (isa<PipeType>(T)) + return TargetInfo::OCLTK_Pipe; + + return TargetInfo::OCLTK_Default; + } + + switch (BT->getKind()) { +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + case BuiltinType::Id: \ + return TargetInfo::OCLTK_Image; +#include "clang/Basic/OpenCLImageTypes.def" + + case BuiltinType::OCLClkEvent: + return TargetInfo::OCLTK_ClkEvent; + + case BuiltinType::OCLEvent: + return TargetInfo::OCLTK_Event; + + case BuiltinType::OCLQueue: + return TargetInfo::OCLTK_Queue; + + case BuiltinType::OCLReserveID: + return TargetInfo::OCLTK_ReserveID; + + case BuiltinType::OCLSampler: + return TargetInfo::OCLTK_Sampler; + + default: + return TargetInfo::OCLTK_Default; + } +} + +LangAS ASTContext::getOpenCLTypeAddrSpace(const Type *T) const { + return Target->getOpenCLTypeAddrSpace(getOpenCLTypeKind(T)); +} + /// BlockRequiresCopying - Returns true if byref variable "D" of type "Ty" /// requires copy/dispose. Note that this must match the logic /// in buildByrefHelpers. @@ -5497,7 +5798,6 @@ bool ASTContext::BlockRequiresCopying(QualType Ty, bool ASTContext::getByrefLifetime(QualType Ty, Qualifiers::ObjCLifetime &LifeTime, bool &HasByrefExtendedLayout) const { - if (!getLangOpts().ObjC1 || getLangOpts().getGC() != LangOptions::NonGC) return false; @@ -5565,14 +5865,14 @@ ASTContext::getInlineVariableDefinitionKind(const VarDecl *VD) const { // In almost all cases, it's a weak definition. auto *First = VD->getFirstDecl(); - if (!First->isConstexpr() || First->isInlineSpecified() || - !VD->isStaticDataMember()) + if (First->isInlineSpecified() || !First->isStaticDataMember()) return InlineVariableDefinitionKind::Weak; // If there's a file-context declaration in this translation unit, it's a // non-discardable definition. for (auto *D : VD->redecls()) - if (D->getLexicalDeclContext()->isFileContext()) + if (D->getLexicalDeclContext()->isFileContext() && + !D->isInlineSpecified() && (D->isConstexpr() || First->isConstexpr())) return InlineVariableDefinitionKind::Strong; // If we've not seen one yet, we don't know. @@ -5602,7 +5902,6 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const { // Compute size of all parameters. // Start with computing size of a pointer in number of bytes. // FIXME: There might(should) be a better way of doing this computation! - SourceLocation Loc; CharUnits PtrSize = getTypeSizeInChars(VoidPtrTy); CharUnits ParmOffset = PtrSize; for (auto PI : Decl->parameters()) { @@ -5610,7 +5909,7 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const { CharUnits sz = getObjCEncodingTypeSize(PType); if (sz.isZero()) continue; - assert (sz.isPositive() && "BlockExpr - Incomplete param type"); + assert(sz.isPositive() && "BlockExpr - Incomplete param type"); ParmOffset += sz; } // Size of the argument frame @@ -5710,7 +6009,6 @@ std::string ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, // Compute size of all parameters. // Start with computing size of a pointer in number of bytes. // FIXME: There might(should) be a better way of doing this computation! - SourceLocation Loc; CharUnits PtrSize = getTypeSizeInChars(VoidPtrTy); // The first two arguments (self and _cmd) are pointers; account for // their size. @@ -5722,8 +6020,8 @@ std::string ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, if (sz.isZero()) continue; - assert (sz.isPositive() && - "getObjCEncodingForMethodDecl - Incomplete param type"); + assert(sz.isPositive() && + "getObjCEncodingForMethodDecl - Incomplete param type"); ParmOffset += sz; } S += charUnitsToString(ParmOffset); @@ -5870,7 +6168,6 @@ ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, /// Another legacy compatibility encoding: 32-bit longs are encoded as /// 'l' or 'L' , but not always. For typedefs, we need to use /// 'i' or 'I' instead if encoding a struct field, or a pointer! -/// void ASTContext::getLegacyIntegralTypeEncoding (QualType &PointeeTy) const { if (isa<TypedefType>(PointeeTy.getTypePtr())) { if (const BuiltinType *BT = PointeeTy->getAs<BuiltinType>()) { @@ -5935,6 +6232,7 @@ static char getObjCEncodingForPrimitiveKind(const ASTContext *C, case BuiltinType::LongDouble: return 'D'; case BuiltinType::NullPtr: return '*'; // like char* + case BuiltinType::Float16: case BuiltinType::Float128: case BuiltinType::Half: // FIXME: potentially need @encodes for these! @@ -6176,9 +6474,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, = dyn_cast<ClassTemplateSpecializationDecl>(RDecl)) { const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); llvm::raw_string_ostream OS(S); - TemplateSpecializationType::PrintTemplateArgumentList(OS, - TemplateArgs.asArray(), - (*this).getPrintingPolicy()); + printTemplateArgumentList(OS, TemplateArgs.asArray(), + getPrintingPolicy()); } } else { S += '?'; @@ -6370,10 +6667,9 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, case Type::Vector: case Type::ExtVector: // Until we have a coherent encoding of these three types, issue warning. - { if (NotEncodedT) - *NotEncodedT = T; - return; - } + if (NotEncodedT) + *NotEncodedT = T; + return; // We could see an undeduced auto type here during error recovery. // Just ignore it. @@ -6557,7 +6853,7 @@ void ASTContext::getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT, TypedefDecl *ASTContext::getObjCIdDecl() const { if (!ObjCIdDecl) { - QualType T = getObjCObjectType(ObjCBuiltinIdTy, { }, { }); + QualType T = getObjCObjectType(ObjCBuiltinIdTy, {}, {}); T = getObjCObjectPointerType(T); ObjCIdDecl = buildImplicitTypedef(T, "id"); } @@ -6574,7 +6870,7 @@ TypedefDecl *ASTContext::getObjCSelDecl() const { TypedefDecl *ASTContext::getObjCClassDecl() const { if (!ObjCClassDecl) { - QualType T = getObjCObjectType(ObjCBuiltinClassTy, { }, { }); + QualType T = getObjCObjectType(ObjCBuiltinClassTy, {}, {}); T = getObjCObjectPointerType(T); ObjCClassDecl = buildImplicitTypedef(T, "Class"); } @@ -7236,7 +7532,7 @@ bool ASTContext::ObjCQualifiedClassTypesAreCompatible(QualType lhs, QualType rhs) { const ObjCObjectPointerType *lhsQID = lhs->getAs<ObjCObjectPointerType>(); const ObjCObjectPointerType *rhsOPT = rhs->getAs<ObjCObjectPointerType>(); - assert ((lhsQID && rhsOPT) && "ObjCQualifiedClassTypesAreCompatible"); + assert((lhsQID && rhsOPT) && "ObjCQualifiedClassTypesAreCompatible"); for (auto *lhsProto : lhsQID->quals()) { bool match = false; @@ -7374,7 +7670,6 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, /// canAssignObjCInterfaces - Return true if the two interface types are /// compatible for assignment from RHS to LHS. This handles validation of any /// protocol qualifiers on the LHS or RHS. -/// bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT) { const ObjCObjectType* LHS = LHSOPT->getObjectType(); @@ -7480,7 +7775,6 @@ bool ASTContext::canAssignObjCInterfacesInBlockPointer( static int compareObjCProtocolsByName(ObjCProtocolDecl * const *lhs, ObjCProtocolDecl * const *rhs) { return (*lhs)->getName().compare((*rhs)->getName()); - } /// getIntersectionOfProtocols - This routine finds the intersection of set @@ -7649,7 +7943,7 @@ QualType ASTContext::areCommonBaseCompatible( } else if (LHS->isSpecialized() != RHS->isSpecialized()) { // If only one has type arguments, the result will not have type // arguments. - LHSTypeArgs = { }; + LHSTypeArgs = {}; anyChanges = true; } @@ -7700,7 +7994,7 @@ QualType ASTContext::areCommonBaseCompatible( } else if (LHS->isSpecialized() != RHS->isSpecialized()) { // If only one has type arguments, the result will not have type // arguments. - RHSTypeArgs = { }; + RHSTypeArgs = {}; anyChanges = true; } @@ -7962,9 +8256,17 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, if (lproto->getTypeQuals() != rproto->getTypeQuals()) return QualType(); - if (!doFunctionTypesMatchOnExtParameterInfos(rproto, lproto)) + SmallVector<FunctionProtoType::ExtParameterInfo, 4> newParamInfos; + bool canUseLeft, canUseRight; + if (!mergeExtParameterInfo(lproto, rproto, canUseLeft, canUseRight, + newParamInfos)) return QualType(); + if (!canUseLeft) + allLTypes = false; + if (!canUseRight) + allRTypes = false; + // Check parameter type compatibility SmallVector<QualType, 10> types; for (unsigned i = 0, n = lproto->getNumParams(); i < n; i++) { @@ -7995,6 +8297,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, FunctionProtoType::ExtProtoInfo EPI = lproto->getExtProtoInfo(); EPI.ExtInfo = einfo; + EPI.ExtParameterInfos = + newParamInfos.empty() ? nullptr : newParamInfos.data(); return getFunctionType(retType, types, EPI); } @@ -8328,7 +8632,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, return QualType(); } - case Type::ObjCObjectPointer: { + case Type::ObjCObjectPointer: if (OfBlockPointer) { if (canAssignObjCInterfacesInBlockPointer( LHS->getAs<ObjCObjectPointerType>(), @@ -8342,38 +8646,59 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, return LHS; return QualType(); - } case Type::Pipe: - { assert(LHS != RHS && "Equivalent pipe types should have already been handled!"); return QualType(); } - } llvm_unreachable("Invalid Type::Class!"); } -bool ASTContext::doFunctionTypesMatchOnExtParameterInfos( - const FunctionProtoType *firstFnType, - const FunctionProtoType *secondFnType) { +bool ASTContext::mergeExtParameterInfo( + const FunctionProtoType *FirstFnType, const FunctionProtoType *SecondFnType, + bool &CanUseFirst, bool &CanUseSecond, + SmallVectorImpl<FunctionProtoType::ExtParameterInfo> &NewParamInfos) { + assert(NewParamInfos.empty() && "param info list not empty"); + CanUseFirst = CanUseSecond = true; + bool FirstHasInfo = FirstFnType->hasExtParameterInfos(); + bool SecondHasInfo = SecondFnType->hasExtParameterInfos(); + // Fast path: if the first type doesn't have ext parameter infos, - // we match if and only if they second type also doesn't have them. - if (!firstFnType->hasExtParameterInfos()) - return !secondFnType->hasExtParameterInfos(); + // we match if and only if the second type also doesn't have them. + if (!FirstHasInfo && !SecondHasInfo) + return true; - // Otherwise, we can only match if the second type has them. - if (!secondFnType->hasExtParameterInfos()) - return false; + bool NeedParamInfo = false; + size_t E = FirstHasInfo ? FirstFnType->getExtParameterInfos().size() + : SecondFnType->getExtParameterInfos().size(); - auto firstEPI = firstFnType->getExtParameterInfos(); - auto secondEPI = secondFnType->getExtParameterInfos(); - assert(firstEPI.size() == secondEPI.size()); + for (size_t I = 0; I < E; ++I) { + FunctionProtoType::ExtParameterInfo FirstParam, SecondParam; + if (FirstHasInfo) + FirstParam = FirstFnType->getExtParameterInfo(I); + if (SecondHasInfo) + SecondParam = SecondFnType->getExtParameterInfo(I); - for (size_t i = 0, n = firstEPI.size(); i != n; ++i) { - if (firstEPI[i] != secondEPI[i]) + // Cannot merge unless everything except the noescape flag matches. + if (FirstParam.withIsNoEscape(false) != SecondParam.withIsNoEscape(false)) return false; + + bool FirstNoEscape = FirstParam.isNoEscape(); + bool SecondNoEscape = SecondParam.isNoEscape(); + bool IsNoEscape = FirstNoEscape && SecondNoEscape; + NewParamInfos.push_back(FirstParam.withIsNoEscape(IsNoEscape)); + if (NewParamInfos.back().getOpaqueValue()) + NeedParamInfo = true; + if (FirstNoEscape != IsNoEscape) + CanUseFirst = false; + if (SecondNoEscape != IsNoEscape) + CanUseSecond = false; } + + if (!NeedParamInfo) + NewParamInfos.clear(); + return true; } @@ -8502,7 +8827,7 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) const { } } -ASTMutationListener::~ASTMutationListener() { } +ASTMutationListener::~ASTMutationListener() = default; void ASTMutationListener::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) {} @@ -8554,7 +8879,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, assert(HowLong <= 2 && "Can't have LLLL modifier"); ++HowLong; break; - case 'N': { + 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!"); @@ -8564,7 +8889,6 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, if (Context.getTargetInfo().getLongWidth() == 32) ++HowLong; break; - } case 'W': // This modifier represents int64 type. assert(!IsSpecialLong && "Can't use two 'N' or 'W' modifiers!"); @@ -8719,10 +9043,9 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, Type = Context.getComplexType(ElementType); break; } - case 'Y' : { + case 'Y': Type = Context.getPointerDiffType(); break; - } case 'P': Type = Context.getFILEType(); if (Type.isNull()) { @@ -8767,8 +9090,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 + LangAS::FirstTargetAddressSpace); + Type = Context.getAddrSpaceQualType(Type, + getLangASFromTargetAS(AddrSpace)); Str = End; } if (c == '*') @@ -8860,6 +9183,12 @@ static GVALinkage basicGVALinkageForFunction(const ASTContext &Context, if (!FD->isExternallyVisible()) return GVA_Internal; + // Non-user-provided functions get emitted as weak definitions with every + // use, no matter whether they've been explicitly instantiated etc. + if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) + if (!MD->isUserProvided()) + return GVA_DiscardableODR; + GVALinkage External; switch (FD->getTemplateSpecializationKind()) { case TSK_Undeclared: @@ -8912,7 +9241,7 @@ static GVALinkage basicGVALinkageForFunction(const ASTContext &Context, } static GVALinkage adjustGVALinkageForAttributes(const ASTContext &Context, - GVALinkage L, const Decl *D) { + const Decl *D, GVALinkage L) { // See http://msdn.microsoft.com/en-us/library/xa0d9ste.aspx // dllexport/dllimport on inline functions. if (D->hasAttr<DLLImportAttr>()) { @@ -8931,25 +9260,37 @@ static GVALinkage adjustGVALinkageForAttributes(const ASTContext &Context, return L; } -GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const { - auto L = adjustGVALinkageForAttributes( - *this, basicGVALinkageForFunction(*this, FD), FD); - auto EK = ExternalASTSource::EK_ReplyHazy; - if (auto *Ext = getExternalSource()) - EK = Ext->hasExternalDefinitions(FD); - switch (EK) { +/// Adjust the GVALinkage for a declaration based on what an external AST source +/// knows about whether there can be other definitions of this declaration. +static GVALinkage +adjustGVALinkageForExternalDefinitionKind(const ASTContext &Ctx, const Decl *D, + GVALinkage L) { + ExternalASTSource *Source = Ctx.getExternalSource(); + if (!Source) + return L; + + switch (Source->hasExternalDefinitions(D)) { case ExternalASTSource::EK_Never: + // Other translation units rely on us to provide the definition. if (L == GVA_DiscardableODR) return GVA_StrongODR; break; + case ExternalASTSource::EK_Always: return GVA_AvailableExternally; + case ExternalASTSource::EK_ReplyHazy: break; } return L; } +GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const { + return adjustGVALinkageForExternalDefinitionKind(*this, FD, + adjustGVALinkageForAttributes(*this, FD, + basicGVALinkageForFunction(*this, FD))); +} + static GVALinkage basicGVALinkageForVariable(const ASTContext &Context, const VarDecl *VD) { if (!VD->isExternallyVisible()) @@ -9028,8 +9369,9 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context, } GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) { - return adjustGVALinkageForAttributes( - *this, basicGVALinkageForVariable(*this, VD), VD); + return adjustGVALinkageForExternalDefinitionKind(*this, VD, + adjustGVALinkageForAttributes(*this, VD, + basicGVALinkageForVariable(*this, VD))); } bool ASTContext::DeclMustBeEmitted(const Decl *D) { @@ -9112,9 +9454,14 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { return false; // Variables that can be needed in other TUs are required. - if (!isDiscardableGVALinkage(GetGVALinkageForVariable(VD))) + auto Linkage = GetGVALinkageForVariable(VD); + if (!isDiscardableGVALinkage(Linkage)) return true; + // We never need to emit a variable that is available in another TU. + if (Linkage == GVA_AvailableExternally) + return false; + // Variables that have destruction with side-effects are required. if (VD->getType().isDestructedType()) return true; @@ -9148,7 +9495,7 @@ CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic, case LangOptions::DCC_CDecl: return CC_C; case LangOptions::DCC_FastCall: - if (getTargetInfo().hasFeature("sse2")) + if (getTargetInfo().hasFeature("sse2") && !IsVariadic) return CC_X86FastCall; break; case LangOptions::DCC_StdCall: @@ -9160,6 +9507,11 @@ CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic, if (!IsVariadic) return CC_X86VectorCall; break; + case LangOptions::DCC_RegCall: + // __regcall cannot be applied to variadic functions. + if (!IsVariadic) + return CC_X86RegCall; + break; } return Target->getDefaultCallingConv(TargetInfo::CCMT_Unknown); } @@ -9196,7 +9548,7 @@ MangleContext *ASTContext::createMangleContext() { llvm_unreachable("Unsupported ABI"); } -CXXABI::~CXXABI() {} +CXXABI::~CXXABI() = default; size_t ASTContext::getSideTableAllocatedMemory() const { return ASTRecordLayouts.getMemorySize() + @@ -9359,9 +9711,7 @@ bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const { return (Size != Align || toBits(sizeChars) > MaxInlineWidthInBits); } -namespace { - -ast_type_traits::DynTypedNode getSingleDynTypedNodeFromParentMap( +static ast_type_traits::DynTypedNode getSingleDynTypedNodeFromParentMap( ASTContext::ParentMapPointers::mapped_type U) { if (const auto *D = U.dyn_cast<const Decl *>()) return ast_type_traits::DynTypedNode::create(*D); @@ -9370,6 +9720,8 @@ ast_type_traits::DynTypedNode getSingleDynTypedNodeFromParentMap( return *U.get<ast_type_traits::DynTypedNode *>(); } +namespace { + /// Template specializations to abstract away from pointers and TypeLocs. /// @{ template <typename T> @@ -9410,7 +9762,9 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) { } private: - typedef RecursiveASTVisitor<ParentMapASTVisitor> VisitorBase; + friend class RecursiveASTVisitor<ParentMapASTVisitor>; + + using VisitorBase = RecursiveASTVisitor<ParentMapASTVisitor>; ParentMapASTVisitor(ASTContext::ParentMapPointers *Parents, ASTContext::ParentMapOtherNodes *OtherParents) @@ -9419,6 +9773,7 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) { bool shouldVisitTemplateInstantiations() const { return true; } + bool shouldVisitImplicitCode() const { return true; } @@ -9508,11 +9863,9 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) { ASTContext::ParentMapPointers *Parents; ASTContext::ParentMapOtherNodes *OtherParents; llvm::SmallVector<ast_type_traits::DynTypedNode, 16> ParentStack; - - friend class RecursiveASTVisitor<ParentMapASTVisitor>; }; -} // anonymous namespace +} // namespace template <typename NodeTy, typename MapTy> static ASTContext::DynTypedNodeList getDynNodeFromMap(const NodeTy &Node, @@ -9568,25 +9921,25 @@ ASTContext::ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, if (!hasSameType(DeclVar->getType(), ImplVar->getType())) return false; } + return (MethodDecl->isVariadic() == MethodImpl->isVariadic()); - } uint64_t ASTContext::getTargetNullPointerValue(QualType QT) const { - unsigned AS; + LangAS AS; if (QT->getUnqualifiedDesugaredType()->isNullPtrType()) - AS = 0; + AS = LangAS::Default; else AS = QT->getPointeeType().getAddressSpace(); return getTargetInfo().getNullPointerValue(AS); } -unsigned ASTContext::getTargetAddressSpace(unsigned AS) const { - if (AS >= LangAS::FirstTargetAddressSpace) - return AS - LangAS::FirstTargetAddressSpace; +unsigned ASTContext::getTargetAddressSpace(LangAS AS) const { + if (isTargetAddressSpace(AS)) + return toTargetAddressSpace(AS); else - return (*AddrSpaceMap)[AS]; + return (*AddrSpaceMap)[(unsigned)AS]; } // Explicitly instantiate this in case a Redeclarable<T> is used from a TU that diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 92ed7da94d8e..157b29fd84b6 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -537,6 +537,7 @@ namespace { void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node); void VisitCXXThisExpr(const CXXThisExpr *Node); void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node); + void VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr *Node); void VisitCXXConstructExpr(const CXXConstructExpr *Node); void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node); void VisitCXXNewExpr(const CXXNewExpr *Node); @@ -1184,7 +1185,7 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { I != E; ++I) dumpCXXCtorInitializer(*I); - if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { if (MD->size_overridden_methods() != 0) { auto dumpOverride = [=](const CXXMethodDecl *D) { @@ -1194,16 +1195,18 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { }; dumpChild([=] { - auto FirstOverrideItr = MD->begin_overridden_methods(); + auto Overrides = MD->overridden_methods(); OS << "Overrides: [ "; - dumpOverride(*FirstOverrideItr); + dumpOverride(*Overrides.begin()); for (const auto *Override : - llvm::make_range(FirstOverrideItr + 1, - MD->end_overridden_methods())) + llvm::make_range(Overrides.begin() + 1, Overrides.end())) { + OS << ", "; dumpOverride(Override); + } OS << " ]"; }); } + } if (D->doesThisDeclarationHaveABody()) dumpStmt(D->getBody()); @@ -1313,6 +1316,16 @@ void ASTDumper::VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D) { dumpStmt(D->getCombiner()); if (auto *Initializer = D->getInitializer()) { OS << " initializer"; + switch (D->getInitializerKind()) { + case OMPDeclareReductionDecl::DirectInit: + OS << " omp_priv = "; + break; + case OMPDeclareReductionDecl::CopyInit: + OS << " omp_priv ()"; + break; + case OMPDeclareReductionDecl::CallInit: + break; + } dumpStmt(Initializer); } } @@ -1362,6 +1375,128 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { if (!D->isCompleteDefinition()) return; + dumpChild([=] { + { + ColorScope Color(*this, DeclKindNameColor); + OS << "DefinitionData"; + } +#define FLAG(fn, name) if (D->fn()) OS << " " #name; + FLAG(isParsingBaseSpecifiers, parsing_base_specifiers); + + FLAG(isGenericLambda, generic); + FLAG(isLambda, lambda); + + FLAG(canPassInRegisters, pass_in_registers); + FLAG(isEmpty, empty); + FLAG(isAggregate, aggregate); + FLAG(isStandardLayout, standard_layout); + FLAG(isTriviallyCopyable, trivially_copyable); + FLAG(isPOD, pod); + FLAG(isTrivial, trivial); + FLAG(isPolymorphic, polymorphic); + FLAG(isAbstract, abstract); + FLAG(isLiteral, literal); + + FLAG(hasUserDeclaredConstructor, has_user_declared_ctor); + FLAG(hasConstexprNonCopyMoveConstructor, has_constexpr_non_copy_move_ctor); + FLAG(hasMutableFields, has_mutable_fields); + FLAG(hasVariantMembers, has_variant_members); + FLAG(allowConstDefaultInit, can_const_default_init); + + dumpChild([=] { + { + ColorScope Color(*this, DeclKindNameColor); + OS << "DefaultConstructor"; + } + FLAG(hasDefaultConstructor, exists); + FLAG(hasTrivialDefaultConstructor, trivial); + FLAG(hasNonTrivialDefaultConstructor, non_trivial); + FLAG(hasUserProvidedDefaultConstructor, user_provided); + FLAG(hasConstexprDefaultConstructor, constexpr); + FLAG(needsImplicitDefaultConstructor, needs_implicit); + FLAG(defaultedDefaultConstructorIsConstexpr, defaulted_is_constexpr); + }); + + dumpChild([=] { + { + ColorScope Color(*this, DeclKindNameColor); + OS << "CopyConstructor"; + } + FLAG(hasSimpleCopyConstructor, simple); + FLAG(hasTrivialCopyConstructor, trivial); + FLAG(hasNonTrivialCopyConstructor, non_trivial); + FLAG(hasUserDeclaredCopyConstructor, user_declared); + FLAG(hasCopyConstructorWithConstParam, has_const_param); + FLAG(needsImplicitCopyConstructor, needs_implicit); + FLAG(needsOverloadResolutionForCopyConstructor, + needs_overload_resolution); + if (!D->needsOverloadResolutionForCopyConstructor()) + FLAG(defaultedCopyConstructorIsDeleted, defaulted_is_deleted); + FLAG(implicitCopyConstructorHasConstParam, implicit_has_const_param); + }); + + dumpChild([=] { + { + ColorScope Color(*this, DeclKindNameColor); + OS << "MoveConstructor"; + } + FLAG(hasMoveConstructor, exists); + FLAG(hasSimpleMoveConstructor, simple); + FLAG(hasTrivialMoveConstructor, trivial); + FLAG(hasNonTrivialMoveConstructor, non_trivial); + FLAG(hasUserDeclaredMoveConstructor, user_declared); + FLAG(needsImplicitMoveConstructor, needs_implicit); + FLAG(needsOverloadResolutionForMoveConstructor, + needs_overload_resolution); + if (!D->needsOverloadResolutionForMoveConstructor()) + FLAG(defaultedMoveConstructorIsDeleted, defaulted_is_deleted); + }); + + dumpChild([=] { + { + ColorScope Color(*this, DeclKindNameColor); + OS << "CopyAssignment"; + } + FLAG(hasTrivialCopyAssignment, trivial); + FLAG(hasNonTrivialCopyAssignment, non_trivial); + FLAG(hasCopyAssignmentWithConstParam, has_const_param); + FLAG(hasUserDeclaredCopyAssignment, user_declared); + FLAG(needsImplicitCopyAssignment, needs_implicit); + FLAG(needsOverloadResolutionForCopyAssignment, needs_overload_resolution); + FLAG(implicitCopyAssignmentHasConstParam, implicit_has_const_param); + }); + + dumpChild([=] { + { + ColorScope Color(*this, DeclKindNameColor); + OS << "MoveAssignment"; + } + FLAG(hasMoveAssignment, exists); + FLAG(hasSimpleMoveAssignment, simple); + FLAG(hasTrivialMoveAssignment, trivial); + FLAG(hasNonTrivialMoveAssignment, non_trivial); + FLAG(hasUserDeclaredMoveAssignment, user_declared); + FLAG(needsImplicitMoveAssignment, needs_implicit); + FLAG(needsOverloadResolutionForMoveAssignment, needs_overload_resolution); + }); + + dumpChild([=] { + { + ColorScope Color(*this, DeclKindNameColor); + OS << "Destructor"; + } + FLAG(hasSimpleDestructor, simple); + FLAG(hasIrrelevantDestructor, irrelevant); + FLAG(hasTrivialDestructor, trivial); + FLAG(hasNonTrivialDestructor, non_trivial); + FLAG(hasUserDeclaredDestructor, user_declared); + FLAG(needsImplicitDestructor, needs_implicit); + FLAG(needsOverloadResolutionForDestructor, needs_overload_resolution); + if (!D->needsOverloadResolutionForDestructor()) + FLAG(defaultedDestructorIsDeleted, defaulted_is_deleted); + }); + }); + for (const auto &I : D->bases()) { dumpChild([=] { if (I.isVirtual()) @@ -2166,12 +2301,24 @@ void ASTDumper::VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node) { << " <" << Node->getCastKindName() << ">"; } +void ASTDumper::VisitCXXUnresolvedConstructExpr( + const CXXUnresolvedConstructExpr *Node) { + VisitExpr(Node); + dumpType(Node->getTypeAsWritten()); + if (Node->isListInitialization()) + OS << " list"; +} + void ASTDumper::VisitCXXConstructExpr(const CXXConstructExpr *Node) { VisitExpr(Node); CXXConstructorDecl *Ctor = Node->getConstructor(); dumpType(Ctor->getType()); if (Node->isElidable()) OS << " elidable"; + if (Node->isListInitialization()) + OS << " list"; + if (Node->isStdInitListInitialization()) + OS << " std::initializer_list"; if (Node->requiresZeroInitialization()) OS << " zeroing"; } diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 2c0bb11cc4bc..84b0d7ecff93 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -58,7 +58,7 @@ namespace clang { QualType VisitExtVectorType(const ExtVectorType *T); QualType VisitFunctionNoProtoType(const FunctionNoProtoType *T); QualType VisitFunctionProtoType(const FunctionProtoType *T); - // FIXME: UnresolvedUsingType + QualType VisitUnresolvedUsingType(const UnresolvedUsingType *T); QualType VisitParenType(const ParenType *T); QualType VisitTypedefType(const TypedefType *T); QualType VisitTypeOfExprType(const TypeOfExprType *T); @@ -77,6 +77,7 @@ namespace clang { QualType VisitTemplateSpecializationType(const TemplateSpecializationType *T); QualType VisitElaboratedType(const ElaboratedType *T); // FIXME: DependentNameType + QualType VisitPackExpansionType(const PackExpansionType *T); // FIXME: DependentTemplateSpecializationType QualType VisitObjCInterfaceType(const ObjCInterfaceType *T); QualType VisitObjCObjectType(const ObjCObjectType *T); @@ -128,27 +129,35 @@ namespace clang { TemplateParameterList *ImportTemplateParameterList( TemplateParameterList *Params); TemplateArgument ImportTemplateArgument(const TemplateArgument &From); - TemplateArgumentLoc ImportTemplateArgumentLoc( - const TemplateArgumentLoc &TALoc, bool &Error); + Optional<TemplateArgumentLoc> ImportTemplateArgumentLoc( + const TemplateArgumentLoc &TALoc); bool ImportTemplateArguments(const TemplateArgument *FromArgs, unsigned NumFromArgs, SmallVectorImpl<TemplateArgument> &ToArgs); + template <typename InContainerTy> + bool ImportTemplateArgumentListInfo(const InContainerTy &Container, + TemplateArgumentListInfo &ToTAInfo); bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, bool Complain = true); bool IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar, bool Complain = true); bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord); bool IsStructuralMatch(EnumConstantDecl *FromEC, EnumConstantDecl *ToEC); + bool IsStructuralMatch(FunctionTemplateDecl *From, + FunctionTemplateDecl *To); bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To); bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To); Decl *VisitDecl(Decl *D); + Decl *VisitEmptyDecl(EmptyDecl *D); Decl *VisitAccessSpecDecl(AccessSpecDecl *D); Decl *VisitStaticAssertDecl(StaticAssertDecl *D); Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D); Decl *VisitNamespaceDecl(NamespaceDecl *D); + Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D); Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias); Decl *VisitTypedefDecl(TypedefDecl *D); Decl *VisitTypeAliasDecl(TypeAliasDecl *D); + Decl *VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D); Decl *VisitLabelDecl(LabelDecl *D); Decl *VisitEnumDecl(EnumDecl *D); Decl *VisitRecordDecl(RecordDecl *D); @@ -170,6 +179,12 @@ namespace clang { Decl *VisitObjCCategoryDecl(ObjCCategoryDecl *D); Decl *VisitObjCProtocolDecl(ObjCProtocolDecl *D); Decl *VisitLinkageSpecDecl(LinkageSpecDecl *D); + Decl *VisitUsingDecl(UsingDecl *D); + Decl *VisitUsingShadowDecl(UsingShadowDecl *D); + Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D); + Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); + Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); + ObjCTypeParamList *ImportObjCTypeParamList(ObjCTypeParamList *list); Decl *VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); @@ -185,6 +200,7 @@ namespace clang { ClassTemplateSpecializationDecl *D); Decl *VisitVarTemplateDecl(VarTemplateDecl *D); Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D); + Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D); // Importing statements DeclGroupRef ImportDeclGroup(DeclGroupRef DG); @@ -265,13 +281,16 @@ namespace clang { Expr *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E); Expr *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE); Expr *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E); + Expr *VisitPackExpansionExpr(PackExpansionExpr *E); Expr *VisitCXXNewExpr(CXXNewExpr *CE); Expr *VisitCXXDeleteExpr(CXXDeleteExpr *E); Expr *VisitCXXConstructExpr(CXXConstructExpr *E); Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E); + Expr *VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E); Expr *VisitExprWithCleanups(ExprWithCleanups *EWC); Expr *VisitCXXThisExpr(CXXThisExpr *E); Expr *VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E); + Expr *VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E); Expr *VisitMemberExpr(MemberExpr *E); Expr *VisitCallExpr(CallExpr *E); Expr *VisitInitListExpr(InitListExpr *E); @@ -280,6 +299,7 @@ namespace clang { Expr *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E); Expr *VisitCXXNamedCastExpr(CXXNamedCastExpr *E); Expr *VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E); + Expr *VisitTypeTraitExpr(TypeTraitExpr *E); template<typename IIter, typename OIter> @@ -566,6 +586,22 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { return Importer.getToContext().getFunctionType(ToResultType, ArgTypes, ToEPI); } +QualType ASTNodeImporter::VisitUnresolvedUsingType( + const UnresolvedUsingType *T) { + UnresolvedUsingTypenameDecl *ToD = cast_or_null<UnresolvedUsingTypenameDecl>( + Importer.Import(T->getDecl())); + if (!ToD) + return QualType(); + + UnresolvedUsingTypenameDecl *ToPrevD = + cast_or_null<UnresolvedUsingTypenameDecl>( + Importer.Import(T->getDecl()->getPreviousDecl())); + if (!ToPrevD && T->getDecl()->getPreviousDecl()) + return QualType(); + + return Importer.getToContext().getTypeDeclType(ToD, ToPrevD); +} + QualType ASTNodeImporter::VisitParenType(const ParenType *T) { QualType ToInnerType = Importer.Import(T->getInnerType()); if (ToInnerType.isNull()) @@ -767,6 +803,15 @@ QualType ASTNodeImporter::VisitElaboratedType(const ElaboratedType *T) { ToQualifier, ToNamedType); } +QualType ASTNodeImporter::VisitPackExpansionType(const PackExpansionType *T) { + QualType Pattern = Importer.Import(T->getPattern()); + if (Pattern.isNull()) + return QualType(); + + return Importer.getToContext().getPackExpansionType(Pattern, + T->getNumExpansions()); +} + QualType ASTNodeImporter::VisitObjCInterfaceType(const ObjCInterfaceType *T) { ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(Importer.Import(T->getDecl())); @@ -1171,9 +1216,8 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) { llvm_unreachable("Invalid template argument kind"); } -TemplateArgumentLoc ASTNodeImporter::ImportTemplateArgumentLoc( - const TemplateArgumentLoc &TALoc, bool &Error) { - Error = false; +Optional<TemplateArgumentLoc> +ASTNodeImporter::ImportTemplateArgumentLoc(const TemplateArgumentLoc &TALoc) { TemplateArgument Arg = ImportTemplateArgument(TALoc.getArgument()); TemplateArgumentLocInfo FromInfo = TALoc.getLocInfo(); TemplateArgumentLocInfo ToInfo; @@ -1181,12 +1225,12 @@ TemplateArgumentLoc ASTNodeImporter::ImportTemplateArgumentLoc( Expr *E = Importer.Import(FromInfo.getAsExpr()); ToInfo = TemplateArgumentLocInfo(E); if (!E) - Error = true; + return None; } else if (Arg.getKind() == TemplateArgument::Type) { if (TypeSourceInfo *TSI = Importer.Import(FromInfo.getAsTypeSourceInfo())) ToInfo = TemplateArgumentLocInfo(TSI); else - Error = true; + return None; } else { ToInfo = TemplateArgumentLocInfo( Importer.Import(FromInfo.getTemplateQualifierLoc()), @@ -1210,6 +1254,18 @@ bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs, return false; } +template <typename InContainerTy> +bool ASTNodeImporter::ImportTemplateArgumentListInfo( + const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo) { + for (const auto &FromLoc : Container) { + if (auto ToLoc = ImportTemplateArgumentLoc(FromLoc)) + ToTAInfo.addArgument(*ToLoc); + else + return true; + } + return false; +} + bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, bool Complain) { // Eliminate a potential failure point where we attempt to re-import @@ -1243,6 +1299,14 @@ bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) { return Ctx.IsStructurallyEquivalent(FromEnum, ToEnum); } +bool ASTNodeImporter::IsStructuralMatch(FunctionTemplateDecl *From, + FunctionTemplateDecl *To) { + StructuralEquivalenceContext Ctx( + Importer.getFromContext(), Importer.getToContext(), + Importer.getNonEquivalentDecls(), false, false); + return Ctx.IsStructurallyEquivalent(From, To); +} + bool ASTNodeImporter::IsStructuralMatch(EnumConstantDecl *FromEC, EnumConstantDecl *ToEC) { @@ -1276,6 +1340,29 @@ Decl *ASTNodeImporter::VisitDecl(Decl *D) { return nullptr; } +Decl *ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) { + // Import the context of this declaration. + DeclContext *DC = Importer.ImportContext(D->getDeclContext()); + if (!DC) + return nullptr; + + DeclContext *LexicalDC = DC; + if (D->getDeclContext() != D->getLexicalDeclContext()) { + LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); + if (!LexicalDC) + return nullptr; + } + + // Import the location of this declaration. + SourceLocation Loc = Importer.Import(D->getLocation()); + + EmptyDecl *ToD = EmptyDecl::Create(Importer.getToContext(), DC, Loc); + ToD->setLexicalDeclContext(LexicalDC); + Importer.Imported(D, ToD); + LexicalDC->addDeclInternal(ToD); + return ToD; +} + Decl *ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { TranslationUnitDecl *ToD = Importer.getToContext().getTranslationUnitDecl(); @@ -1410,6 +1497,44 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { return ToNamespace; } +Decl *ASTNodeImporter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { + // Import the major distinguishing characteristics of this namespace. + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *LookupD; + if (ImportDeclParts(D, DC, LexicalDC, Name, LookupD, Loc)) + return nullptr; + if (LookupD) + return LookupD; + + // NOTE: No conflict resolution is done for namespace aliases now. + + NamespaceDecl *TargetDecl = cast_or_null<NamespaceDecl>( + Importer.Import(D->getNamespace())); + if (!TargetDecl) + return nullptr; + + IdentifierInfo *ToII = Importer.Import(D->getIdentifier()); + if (!ToII) + return nullptr; + + NestedNameSpecifierLoc ToQLoc = Importer.Import(D->getQualifierLoc()); + if (D->getQualifierLoc() && !ToQLoc) + return nullptr; + + NamespaceAliasDecl *ToD = NamespaceAliasDecl::Create( + Importer.getToContext(), DC, Importer.Import(D->getNamespaceLoc()), + Importer.Import(D->getAliasLoc()), ToII, ToQLoc, + Importer.Import(D->getTargetNameLoc()), TargetDecl); + + ToD->setLexicalDeclContext(LexicalDC); + Importer.Imported(D, ToD); + LexicalDC->addDeclInternal(ToD); + + return ToD; +} + Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { // Import the major distinguishing characteristics of this typedef. DeclContext *DC, *LexicalDC; @@ -1487,6 +1612,63 @@ Decl *ASTNodeImporter::VisitTypeAliasDecl(TypeAliasDecl *D) { return VisitTypedefNameDecl(D, /*IsAlias=*/true); } +Decl *ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { + // Import the major distinguishing characteristics of this typedef. + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return nullptr; + if (ToD) + return ToD; + + // If this typedef is not in block scope, determine whether we've + // seen a typedef with the same name (that we can merge with) or any + // other entity by that name (which name lookup could conflict with). + if (!DC->isFunctionOrMethod()) { + SmallVector<NamedDecl *, 4> ConflictingDecls; + unsigned IDNS = Decl::IDNS_Ordinary; + SmallVector<NamedDecl *, 2> FoundDecls; + DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) + continue; + if (auto *FoundAlias = + dyn_cast<TypeAliasTemplateDecl>(FoundDecls[I])) + return Importer.Imported(D, FoundAlias); + ConflictingDecls.push_back(FoundDecls[I]); + } + + if (!ConflictingDecls.empty()) { + Name = Importer.HandleNameConflict(Name, DC, IDNS, + ConflictingDecls.data(), + ConflictingDecls.size()); + if (!Name) + return nullptr; + } + } + + TemplateParameterList *Params = ImportTemplateParameterList( + D->getTemplateParameters()); + if (!Params) + return nullptr; + + NamedDecl *TemplDecl = cast_or_null<NamedDecl>( + Importer.Import(D->getTemplatedDecl())); + if (!TemplDecl) + return nullptr; + + TypeAliasTemplateDecl *ToAlias = TypeAliasTemplateDecl::Create( + Importer.getToContext(), DC, Loc, Name, Params, TemplDecl); + + ToAlias->setAccess(D->getAccess()); + ToAlias->setLexicalDeclContext(LexicalDC); + Importer.Imported(D, ToAlias); + LexicalDC->addDeclInternal(ToAlias); + return ToD; +} + Decl *ASTNodeImporter::VisitLabelDecl(LabelDecl *D) { // Import the major distinguishing characteristics of this label. DeclContext *DC, *LexicalDC; @@ -1752,6 +1934,31 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { } D2 = D2CXX; D2->setAccess(D->getAccess()); + + Importer.Imported(D, D2); + + if (ClassTemplateDecl *FromDescribed = + DCXX->getDescribedClassTemplate()) { + ClassTemplateDecl *ToDescribed = cast_or_null<ClassTemplateDecl>( + Importer.Import(FromDescribed)); + if (!ToDescribed) + return nullptr; + D2CXX->setDescribedClassTemplate(ToDescribed); + + } else if (MemberSpecializationInfo *MemberInfo = + DCXX->getMemberSpecializationInfo()) { + TemplateSpecializationKind SK = + MemberInfo->getTemplateSpecializationKind(); + CXXRecordDecl *FromInst = DCXX->getInstantiatedFromMemberClass(); + CXXRecordDecl *ToInst = + cast_or_null<CXXRecordDecl>(Importer.Import(FromInst)); + if (FromInst && !ToInst) + return nullptr; + D2CXX->setInstantiationOfMemberClass(ToInst, SK); + D2CXX->getMemberSpecializationInfo()->setPointOfInstantiation( + Importer.Import(MemberInfo->getPointOfInstantiation())); + } + } else { D2 = RecordDecl::Create(Importer.getToContext(), D->getTagKind(), DC, StartLoc, Loc, Name.getAsIdentifierInfo()); @@ -1846,6 +2053,8 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { if (ToD) return ToD; + const FunctionDecl *FoundWithoutBody = nullptr; + // Try to find a function in our own ("to") context with the same name, same // type, and in the same context as the function we're importing. if (!LexicalDC->isFunctionOrMethod()) { @@ -1863,6 +2072,13 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { if (Importer.IsStructurallyEquivalent(D->getType(), FoundFunction->getType())) { // FIXME: Actually try to merge the body and other attributes. + const FunctionDecl *FromBodyDecl = nullptr; + D->hasBody(FromBodyDecl); + if (D == FromBodyDecl && !FoundFunction->hasBody()) { + // This function is needed to merge completely. + FoundWithoutBody = FoundFunction; + break; + } return Importer.Imported(D, FoundFunction); } @@ -2013,6 +2229,12 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } ToFunction->setParams(Parameters); + if (FoundWithoutBody) { + auto *Recent = const_cast<FunctionDecl *>( + FoundWithoutBody->getMostRecentDecl()); + ToFunction->setPreviousDecl(Recent); + } + if (usedDifferentExceptionSpec) { // Update FunctionProtoType::ExtProtoInfo. QualType T = Importer.Import(D->getType()); @@ -2876,6 +3098,178 @@ Decl *ASTNodeImporter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { return ToLinkageSpec; } +Decl *ASTNodeImporter::VisitUsingDecl(UsingDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD = nullptr; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return nullptr; + if (ToD) + return ToD; + + DeclarationNameInfo NameInfo(Name, + Importer.Import(D->getNameInfo().getLoc())); + ImportDeclarationNameLoc(D->getNameInfo(), NameInfo); + + UsingDecl *ToUsing = UsingDecl::Create(Importer.getToContext(), DC, + Importer.Import(D->getUsingLoc()), + Importer.Import(D->getQualifierLoc()), + NameInfo, D->hasTypename()); + ToUsing->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToUsing); + Importer.Imported(D, ToUsing); + + if (NamedDecl *FromPattern = + Importer.getFromContext().getInstantiatedFromUsingDecl(D)) { + if (NamedDecl *ToPattern = + dyn_cast_or_null<NamedDecl>(Importer.Import(FromPattern))) + Importer.getToContext().setInstantiatedFromUsingDecl(ToUsing, ToPattern); + else + return nullptr; + } + + for (UsingShadowDecl *FromShadow : D->shadows()) { + if (UsingShadowDecl *ToShadow = + dyn_cast_or_null<UsingShadowDecl>(Importer.Import(FromShadow))) + ToUsing->addShadowDecl(ToShadow); + else + // FIXME: We return a nullptr here but the definition is already created + // and available with lookups. How to fix this?.. + return nullptr; + } + return ToUsing; +} + +Decl *ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD = nullptr; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return nullptr; + if (ToD) + return ToD; + + UsingDecl *ToUsing = dyn_cast_or_null<UsingDecl>( + Importer.Import(D->getUsingDecl())); + if (!ToUsing) + return nullptr; + + NamedDecl *ToTarget = dyn_cast_or_null<NamedDecl>( + Importer.Import(D->getTargetDecl())); + if (!ToTarget) + return nullptr; + + UsingShadowDecl *ToShadow = UsingShadowDecl::Create( + Importer.getToContext(), DC, Loc, ToUsing, ToTarget); + + ToShadow->setLexicalDeclContext(LexicalDC); + ToShadow->setAccess(D->getAccess()); + Importer.Imported(D, ToShadow); + + if (UsingShadowDecl *FromPattern = + Importer.getFromContext().getInstantiatedFromUsingShadowDecl(D)) { + if (UsingShadowDecl *ToPattern = + dyn_cast_or_null<UsingShadowDecl>(Importer.Import(FromPattern))) + Importer.getToContext().setInstantiatedFromUsingShadowDecl(ToShadow, + ToPattern); + else + // FIXME: We return a nullptr here but the definition is already created + // and available with lookups. How to fix this?.. + return nullptr; + } + + LexicalDC->addDeclInternal(ToShadow); + + return ToShadow; +} + + +Decl *ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD = nullptr; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return nullptr; + if (ToD) + return ToD; + + DeclContext *ToComAncestor = Importer.ImportContext(D->getCommonAncestor()); + if (!ToComAncestor) + return nullptr; + + NamespaceDecl *ToNominated = cast_or_null<NamespaceDecl>( + Importer.Import(D->getNominatedNamespace())); + if (!ToNominated) + return nullptr; + + UsingDirectiveDecl *ToUsingDir = UsingDirectiveDecl::Create( + Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), + Importer.Import(D->getNamespaceKeyLocation()), + Importer.Import(D->getQualifierLoc()), + Importer.Import(D->getIdentLocation()), ToNominated, ToComAncestor); + ToUsingDir->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToUsingDir); + Importer.Imported(D, ToUsingDir); + + return ToUsingDir; +} + +Decl *ASTNodeImporter::VisitUnresolvedUsingValueDecl( + UnresolvedUsingValueDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD = nullptr; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return nullptr; + if (ToD) + return ToD; + + DeclarationNameInfo NameInfo(Name, Importer.Import(D->getNameInfo().getLoc())); + ImportDeclarationNameLoc(D->getNameInfo(), NameInfo); + + UnresolvedUsingValueDecl *ToUsingValue = UnresolvedUsingValueDecl::Create( + Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), + Importer.Import(D->getQualifierLoc()), NameInfo, + Importer.Import(D->getEllipsisLoc())); + + Importer.Imported(D, ToUsingValue); + ToUsingValue->setAccess(D->getAccess()); + ToUsingValue->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToUsingValue); + + return ToUsingValue; +} + +Decl *ASTNodeImporter::VisitUnresolvedUsingTypenameDecl( + UnresolvedUsingTypenameDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD = nullptr; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return nullptr; + if (ToD) + return ToD; + + UnresolvedUsingTypenameDecl *ToUsing = UnresolvedUsingTypenameDecl::Create( + Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), + Importer.Import(D->getTypenameLoc()), + Importer.Import(D->getQualifierLoc()), Loc, Name, + Importer.Import(D->getEllipsisLoc())); + + Importer.Imported(D, ToUsing); + ToUsing->setAccess(D->getAccess()); + ToUsing->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToUsing); + + return ToUsing; +} + + bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, ObjCInterfaceDecl *To, ImportDefinitionKind Kind) { @@ -3453,7 +3847,6 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { CXXRecordDecl *DTemplated = D->getTemplatedDecl(); // Create the declaration that is being templated. - // Create the declaration that is being templated. CXXRecordDecl *D2Templated = cast_or_null<CXXRecordDecl>( Importer.Import(DTemplated)); if (!D2Templated) @@ -3560,11 +3953,10 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( 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) + if (auto ToLoc = ImportTemplateArgumentLoc(ASTTemplateArgs[I])) + ToTAInfo.addArgument(*ToLoc); + else return nullptr; - ToTAInfo.addArgument(ToLoc); } QualType CanonInjType = Importer.Import( @@ -3832,6 +4224,64 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( return D2; } +Decl *ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD; + + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return nullptr; + + if (ToD) + return ToD; + + // Try to find a function in our own ("to") context with the same name, same + // type, and in the same context as the function we're importing. + if (!LexicalDC->isFunctionOrMethod()) { + unsigned IDNS = Decl::IDNS_Ordinary; + SmallVector<NamedDecl *, 2> FoundDecls; + DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) + continue; + + if (FunctionTemplateDecl *FoundFunction = + dyn_cast<FunctionTemplateDecl>(FoundDecls[I])) { + if (FoundFunction->hasExternalFormalLinkage() && + D->hasExternalFormalLinkage()) { + if (IsStructuralMatch(D, FoundFunction)) { + Importer.Imported(D, FoundFunction); + // FIXME: Actually try to merge the body and other attributes. + return FoundFunction; + } + } + } + } + } + + TemplateParameterList *Params = + ImportTemplateParameterList(D->getTemplateParameters()); + if (!Params) + return nullptr; + + FunctionDecl *TemplatedFD = + cast_or_null<FunctionDecl>(Importer.Import(D->getTemplatedDecl())); + if (!TemplatedFD) + return nullptr; + + FunctionTemplateDecl *ToFunc = FunctionTemplateDecl::Create( + Importer.getToContext(), DC, Loc, Name, Params, TemplatedFD); + + TemplatedFD->setDescribedFunctionTemplate(ToFunc); + ToFunc->setAccess(D->getAccess()); + ToFunc->setLexicalDeclContext(LexicalDC); + Importer.Imported(D, ToFunc); + + LexicalDC->addDeclInternal(ToFunc); + return ToFunc; +} + //---------------------------------------------------------------------------- // Import Statements //---------------------------------------------------------------------------- @@ -3968,12 +4418,16 @@ Stmt *ASTNodeImporter::VisitCaseStmt(CaseStmt *S) { Expr *ToRHS = Importer.Import(S->getRHS()); if (!ToRHS && S->getRHS()) return nullptr; + Stmt *ToSubStmt = Importer.Import(S->getSubStmt()); + if (!ToSubStmt && S->getSubStmt()) + return nullptr; SourceLocation ToCaseLoc = Importer.Import(S->getCaseLoc()); SourceLocation ToEllipsisLoc = Importer.Import(S->getEllipsisLoc()); SourceLocation ToColonLoc = Importer.Import(S->getColonLoc()); - return new (Importer.getToContext()) CaseStmt(ToLHS, ToRHS, - ToCaseLoc, ToEllipsisLoc, - ToColonLoc); + CaseStmt *ToStmt = new (Importer.getToContext()) + CaseStmt(ToLHS, ToRHS, ToCaseLoc, ToEllipsisLoc, ToColonLoc); + ToStmt->setSubStmt(ToSubStmt); + return ToStmt; } Stmt *ASTNodeImporter::VisitDefaultStmt(DefaultStmt *S) { @@ -4443,11 +4897,10 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { TemplateArgumentListInfo *ResInfo = nullptr; if (E->hasExplicitTemplateArgs()) { for (const auto &FromLoc : E->template_arguments()) { - bool Error = false; - TemplateArgumentLoc ToTALoc = ImportTemplateArgumentLoc(FromLoc, Error); - if (Error) + if (auto ToTALoc = ImportTemplateArgumentLoc(FromLoc)) + ToTAInfo.addArgument(*ToTALoc); + else return nullptr; - ToTAInfo.addArgument(ToTALoc); } ResInfo = &ToTAInfo; } @@ -5161,6 +5614,20 @@ ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { return ToMTE; } +Expr *ASTNodeImporter::VisitPackExpansionExpr(PackExpansionExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *Pattern = Importer.Import(E->getPattern()); + if (!Pattern) + return nullptr; + + return new (Importer.getToContext()) PackExpansionExpr( + T, Pattern, Importer.Import(E->getEllipsisLoc()), + E->getNumExpansions()); +} + Expr *ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *CE) { QualType T = Importer.Import(CE->getType()); if (T.isNull()) @@ -5344,6 +5811,80 @@ Expr *ASTNodeImporter::VisitMemberExpr(MemberExpr *E) { E->getObjectKind()); } +Expr *ASTNodeImporter::VisitCXXPseudoDestructorExpr( + CXXPseudoDestructorExpr *E) { + + Expr *BaseE = Importer.Import(E->getBase()); + if (!BaseE) + return nullptr; + + TypeSourceInfo *ScopeInfo = Importer.Import(E->getScopeTypeInfo()); + if (!ScopeInfo && E->getScopeTypeInfo()) + return nullptr; + + PseudoDestructorTypeStorage Storage; + if (IdentifierInfo *FromII = E->getDestroyedTypeIdentifier()) { + IdentifierInfo *ToII = Importer.Import(FromII); + if (!ToII) + return nullptr; + Storage = PseudoDestructorTypeStorage( + ToII, Importer.Import(E->getDestroyedTypeLoc())); + } else { + TypeSourceInfo *TI = Importer.Import(E->getDestroyedTypeInfo()); + if (!TI) + return nullptr; + Storage = PseudoDestructorTypeStorage(TI); + } + + return new (Importer.getToContext()) CXXPseudoDestructorExpr( + Importer.getToContext(), BaseE, E->isArrow(), + Importer.Import(E->getOperatorLoc()), + Importer.Import(E->getQualifierLoc()), + ScopeInfo, Importer.Import(E->getColonColonLoc()), + Importer.Import(E->getTildeLoc()), Storage); +} + +Expr *ASTNodeImporter::VisitCXXDependentScopeMemberExpr( + CXXDependentScopeMemberExpr *E) { + Expr *Base = nullptr; + if (!E->isImplicitAccess()) { + Base = Importer.Import(E->getBase()); + if (!Base) + return nullptr; + } + + QualType BaseType = Importer.Import(E->getBaseType()); + if (BaseType.isNull()) + return nullptr; + + TemplateArgumentListInfo ToTAInfo(Importer.Import(E->getLAngleLoc()), + Importer.Import(E->getRAngleLoc())); + TemplateArgumentListInfo *ResInfo = nullptr; + if (E->hasExplicitTemplateArgs()) { + if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo)) + return nullptr; + ResInfo = &ToTAInfo; + } + + DeclarationName Name = Importer.Import(E->getMember()); + if (!E->getMember().isEmpty() && Name.isEmpty()) + return nullptr; + + DeclarationNameInfo MemberNameInfo(Name, Importer.Import(E->getMemberLoc())); + // Import additional name location/type info. + ImportDeclarationNameLoc(E->getMemberNameInfo(), MemberNameInfo); + auto ToFQ = Importer.Import(E->getFirstQualifierFoundInScope()); + if (!ToFQ && E->getFirstQualifierFoundInScope()) + return nullptr; + + return CXXDependentScopeMemberExpr::Create( + Importer.getToContext(), Base, BaseType, E->isArrow(), + Importer.Import(E->getOperatorLoc()), + Importer.Import(E->getQualifierLoc()), + Importer.Import(E->getTemplateKeywordLoc()), + cast_or_null<NamedDecl>(ToFQ), MemberNameInfo, ResInfo); +} + Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) @@ -5510,6 +6051,26 @@ Expr *ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr( Replacement); } +Expr *ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) { + QualType ToType = Importer.Import(E->getType()); + if (ToType.isNull()) + return nullptr; + + SmallVector<TypeSourceInfo *, 4> ToArgs(E->getNumArgs()); + if (ImportContainerChecked(E->getArgs(), ToArgs)) + return nullptr; + + // According to Sema::BuildTypeTrait(), if E is value-dependent, + // Value is always false. + bool ToValue = false; + if (!E->isValueDependent()) + ToValue = E->getValue(); + + return TypeTraitExpr::Create( + Importer.getToContext(), ToType, Importer.Import(E->getLocStart()), + E->getTrait(), ToArgs, Importer.Import(E->getLocEnd()), ToValue); +} + void ASTNodeImporter::ImportOverrides(CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod) { for (auto *FromOverriddenMethod : FromMethod->overridden_methods()) diff --git a/lib/AST/ASTStructuralEquivalence.cpp b/lib/AST/ASTStructuralEquivalence.cpp index ea7faab767ed..0df8e5653f3b 100644 --- a/lib/AST/ASTStructuralEquivalence.cpp +++ b/lib/AST/ASTStructuralEquivalence.cpp @@ -365,6 +365,21 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, break; } + case Type::DependentAddressSpace: { + const DependentAddressSpaceType *DepAddressSpace1 = + cast<DependentAddressSpaceType>(T1); + const DependentAddressSpaceType *DepAddressSpace2 = + cast<DependentAddressSpaceType>(T2); + if (!IsStructurallyEquivalent(Context, DepAddressSpace1->getAddrSpaceExpr(), + DepAddressSpace2->getAddrSpaceExpr())) + return false; + if (!IsStructurallyEquivalent(Context, DepAddressSpace1->getPointeeType(), + DepAddressSpace2->getPointeeType())) + return false; + + break; + } + case Type::DependentSizedExtVector: { const DependentSizedExtVectorType *Vec1 = cast<DependentSizedExtVectorType>(T1); diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index ab9b59184294..a6f1027856c7 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -20,6 +20,7 @@ add_clang_library(clangAST CommentLexer.cpp CommentParser.cpp CommentSema.cpp + DataCollection.cpp Decl.cpp DeclarationName.cpp DeclBase.cpp @@ -48,6 +49,7 @@ add_clang_library(clangAST ODRHash.cpp OpenMPClause.cpp ParentMap.cpp + QualTypeNames.cpp RawCommentList.cpp RecordLayout.cpp RecordLayoutBuilder.cpp diff --git a/lib/AST/CXXABI.h b/lib/AST/CXXABI.h index 924ef00e8147..06295b58178b 100644 --- a/lib/AST/CXXABI.h +++ b/lib/AST/CXXABI.h @@ -31,9 +31,16 @@ class CXXABI { public: virtual ~CXXABI(); - /// Returns the width and alignment of a member pointer in bits. - virtual std::pair<uint64_t, unsigned> - getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const = 0; + struct MemberPointerInfo { + uint64_t Width; + unsigned Align; + bool HasPadding; + }; + + /// Returns the width and alignment of a member pointer in bits, as well as + /// whether it has padding. + virtual MemberPointerInfo + getMemberPointerInfo(const MemberPointerType *MPT) const = 0; /// Returns the default calling convention for C++ methods. virtual CallingConv getDefaultMethodCallConv(bool isVariadic) const = 0; diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp index fc4d8b137337..24e96ba38015 100644 --- a/lib/AST/CXXInheritance.cpp +++ b/lib/AST/CXXInheritance.cpp @@ -1,4 +1,4 @@ -//===------ CXXInheritance.cpp - C++ Inheritance ----------------*- C++ -*-===// +//===- CXXInheritance.cpp - C++ Inheritance -------------------------------===// // // The LLVM Compiler Infrastructure // @@ -10,13 +10,27 @@ // This file provides routines that help analyzing C++ inheritance hierarchies. // //===----------------------------------------------------------------------===// + #include "clang/AST/CXXInheritance.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/RecordLayout.h" +#include "clang/AST/TemplateName.h" +#include "clang/AST/Type.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Casting.h" #include <algorithm> +#include <utility> +#include <cassert> +#include <vector> using namespace clang; @@ -26,7 +40,7 @@ void CXXBasePaths::ComputeDeclsFound() { assert(NumDeclsFound == 0 && !DeclsFound && "Already computed the set of declarations"); - llvm::SetVector<NamedDecl *, SmallVector<NamedDecl *, 8> > Decls; + llvm::SetVector<NamedDecl *, SmallVector<NamedDecl *, 8>> Decls; for (paths_iterator Path = begin(), PathEnd = end(); Path != PathEnd; ++Path) Decls.insert(Path->Decls.front()); @@ -419,8 +433,8 @@ bool CXXRecordDecl::FindTagMember(const CXXBaseSpecifier *Specifier, static bool findOrdinaryMember(RecordDecl *BaseRecord, CXXBasePath &Path, DeclarationName Name) { - const unsigned IDNS = clang::Decl::IDNS_Ordinary | clang::Decl::IDNS_Tag | - clang::Decl::IDNS_Member; + const unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | + Decl::IDNS_Member; for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); Path.Decls = Path.Decls.slice(1)) { @@ -550,26 +564,27 @@ void OverridingMethods::replaceAll(UniqueVirtualMethod Overriding) { } } - namespace { - class FinalOverriderCollector { - /// \brief The number of subobjects of a given class type that - /// occur within the class hierarchy. - llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCount; - /// \brief Overriders for each virtual base subobject. - llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *> VirtualOverriders; +class FinalOverriderCollector { + /// \brief The number of subobjects of a given class type that + /// occur within the class hierarchy. + llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCount; - CXXFinalOverriderMap FinalOverriders; + /// \brief Overriders for each virtual base subobject. + llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *> VirtualOverriders; - public: - ~FinalOverriderCollector(); + CXXFinalOverriderMap FinalOverriders; - void Collect(const CXXRecordDecl *RD, bool VirtualBase, - const CXXRecordDecl *InVirtualSubobject, - CXXFinalOverriderMap &Overriders); - }; -} +public: + ~FinalOverriderCollector(); + + void Collect(const CXXRecordDecl *RD, bool VirtualBase, + const CXXRecordDecl *InVirtualSubobject, + CXXFinalOverriderMap &Overriders); +}; + +} // namespace void FinalOverriderCollector::Collect(const CXXRecordDecl *RD, bool VirtualBase, @@ -635,9 +650,11 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD, continue; CXXMethodDecl *CanonM = cast<CXXMethodDecl>(M->getCanonicalDecl()); + using OverriddenMethodsRange = + llvm::iterator_range<CXXMethodDecl::method_iterator>; + OverriddenMethodsRange OverriddenMethods = CanonM->overridden_methods(); - if (CanonM->begin_overridden_methods() - == CanonM->end_overridden_methods()) { + if (OverriddenMethods.begin() == OverriddenMethods.end()) { // This is a new virtual function that does not override any // other virtual function. Add it to the map of virtual // functions for which we are tracking overridders. @@ -656,11 +673,7 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD, // overrider. To do so, we dig down to the original virtual // functions using data recursion and update all of the methods it // overrides. - typedef llvm::iterator_range<CXXMethodDecl::method_iterator> - OverriddenMethods; - SmallVector<OverriddenMethods, 4> Stack; - Stack.push_back(llvm::make_range(CanonM->begin_overridden_methods(), - CanonM->end_overridden_methods())); + SmallVector<OverriddenMethodsRange, 4> Stack(1, OverriddenMethods); while (!Stack.empty()) { for (const CXXMethodDecl *OM : Stack.pop_back_val()) { const CXXMethodDecl *CanonOM = OM->getCanonicalDecl(); @@ -678,14 +691,13 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD, UniqueVirtualMethod(CanonM, SubobjectNumber, InVirtualSubobject)); - if (CanonOM->begin_overridden_methods() - == CanonOM->end_overridden_methods()) + auto OverriddenMethods = CanonOM->overridden_methods(); + if (OverriddenMethods.begin() == OverriddenMethods.end()) continue; // Continue recursion to the methods that this virtual method // overrides. - Stack.push_back(llvm::make_range(CanonOM->begin_overridden_methods(), - CanonOM->end_overridden_methods())); + Stack.push_back(OverriddenMethods); } } diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp index 403454d3ab7e..6c2019e1a72b 100644 --- a/lib/AST/CommentSema.cpp +++ b/lib/AST/CommentSema.cpp @@ -813,7 +813,7 @@ bool Sema::isAnyFunctionDecl() { } bool Sema::isFunctionOrMethodVariadic() { - if (!isAnyFunctionDecl() && !isObjCMethodDecl() && !isFunctionTemplateDecl()) + if (!isFunctionDecl() || !ThisDeclInfo->CurrentDecl) return false; if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ThisDeclInfo->CurrentDecl)) @@ -824,6 +824,14 @@ bool Sema::isFunctionOrMethodVariadic() { if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ThisDeclInfo->CurrentDecl)) return MD->isVariadic(); + if (const TypedefNameDecl *TD = + dyn_cast<TypedefNameDecl>(ThisDeclInfo->CurrentDecl)) { + QualType Type = TD->getUnderlyingType(); + if (Type->isFunctionPointerType() || Type->isBlockPointerType()) + Type = Type->getPointeeType(); + if (const auto *FT = Type->getAs<FunctionProtoType>()) + return FT->isVariadic(); + } return false; } diff --git a/lib/AST/DataCollection.cpp b/lib/AST/DataCollection.cpp new file mode 100644 index 000000000000..c2ecabe8e6f8 --- /dev/null +++ b/lib/AST/DataCollection.cpp @@ -0,0 +1,50 @@ +//===-- DataCollection.cpp --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/DataCollection.h" + +#include "clang/Lex/Lexer.h" + +namespace clang { +namespace data_collection { + +/// Prints the macro name that contains the given SourceLocation into the given +/// raw_string_ostream. +static void printMacroName(llvm::raw_string_ostream &MacroStack, + ASTContext &Context, SourceLocation Loc) { + MacroStack << Lexer::getImmediateMacroName(Loc, Context.getSourceManager(), + Context.getLangOpts()); + + // Add an empty space at the end as a padding to prevent + // that macro names concatenate to the names of other macros. + MacroStack << " "; +} + +/// Returns a string that represents all macro expansions that expanded into the +/// given SourceLocation. +/// +/// If 'getMacroStack(A) == getMacroStack(B)' is true, then the SourceLocations +/// A and B are expanded from the same macros in the same order. +std::string getMacroStack(SourceLocation Loc, ASTContext &Context) { + std::string MacroStack; + llvm::raw_string_ostream MacroStackStream(MacroStack); + SourceManager &SM = Context.getSourceManager(); + + // Iterate over all macros that expanded into the given SourceLocation. + while (Loc.isMacroID()) { + // Add the macro name to the stream. + printMacroName(MacroStackStream, Context, Loc); + Loc = SM.getImmediateMacroCallerLoc(Loc); + } + MacroStackStream.flush(); + return MacroStack; +} + +} // end namespace data_collection +} // end namespace clang diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 573a98efe980..2f51ec31a7bd 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1,4 +1,4 @@ -//===--- Decl.cpp - Declaration AST Node Implementation -------------------===// +//===- Decl.cpp - Declaration AST Node Implementation ---------------------===// // // The LLVM Compiler Infrastructure // @@ -12,27 +12,62 @@ //===----------------------------------------------------------------------===// #include "clang/AST/Decl.h" +#include "Linkage.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTLambda.h" #include "clang/AST/ASTMutationListener.h" -#include "clang/AST/Attr.h" +#include "clang/AST/CanonicalType.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ExternalASTSource.h" #include "clang/AST/PrettyPrinter.h" +#include "clang/AST/Redeclarable.h" #include "clang/AST/Stmt.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/Linkage.h" #include "clang/Basic/Module.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SanitizerBlacklist.h" +#include "clang/Basic/Sanitizers.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" #include "clang/Basic/Specifiers.h" +#include "clang/Basic/TargetCXXABI.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Basic/Visibility.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" #include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstring> +#include <memory> +#include <string> +#include <tuple> +#include <type_traits> using namespace clang; @@ -47,7 +82,7 @@ bool Decl::isOutOfLine() const { TranslationUnitDecl::TranslationUnitDecl(ASTContext &ctx) : Decl(TranslationUnit, nullptr, SourceLocation()), - DeclContext(TranslationUnit), Ctx(ctx), AnonymousNamespace(nullptr) {} + DeclContext(TranslationUnit), Ctx(ctx) {} //===----------------------------------------------------------------------===// // NamedDecl Implementation @@ -99,63 +134,25 @@ TranslationUnitDecl::TranslationUnitDecl(ASTContext &ctx) // and 'matcher' is a type only matters when looking for attributes // and settings from the immediate context. -const unsigned IgnoreExplicitVisibilityBit = 2; -const unsigned IgnoreAllVisibilityBit = 4; - -/// Kinds of LV computation. The linkage side of the computation is -/// always the same, but different things can change how visibility is -/// computed. -enum LVComputationKind { - /// Do an LV computation for, ultimately, a type. - /// Visibility may be restricted by type visibility settings and - /// the visibility of template arguments. - LVForType = NamedDecl::VisibilityForType, - - /// Do an LV computation for, ultimately, a non-type declaration. - /// Visibility may be restricted by value visibility settings and - /// the visibility of template arguments. - LVForValue = NamedDecl::VisibilityForValue, - - /// Do an LV computation for, ultimately, a type that already has - /// some sort of explicit visibility. Visibility may only be - /// restricted by the visibility of template arguments. - LVForExplicitType = (LVForType | IgnoreExplicitVisibilityBit), - - /// Do an LV computation for, ultimately, a non-type declaration - /// that already has some sort of explicit visibility. Visibility - /// may only be restricted by the visibility of template arguments. - LVForExplicitValue = (LVForValue | IgnoreExplicitVisibilityBit), - - /// Do an LV computation when we only care about the linkage. - LVForLinkageOnly = - LVForValue | IgnoreExplicitVisibilityBit | IgnoreAllVisibilityBit -}; - /// Does this computation kind permit us to consider additional /// visibility settings from attributes and the like? static bool hasExplicitVisibilityAlready(LVComputationKind computation) { - return ((unsigned(computation) & IgnoreExplicitVisibilityBit) != 0); + return computation.IgnoreExplicitVisibility; } /// Given an LVComputationKind, return one of the same type/value sort /// that records that it already has explicit visibility. static LVComputationKind -withExplicitVisibilityAlready(LVComputationKind oldKind) { - LVComputationKind newKind = - static_cast<LVComputationKind>(unsigned(oldKind) | - IgnoreExplicitVisibilityBit); - assert(oldKind != LVForType || newKind == LVForExplicitType); - assert(oldKind != LVForValue || newKind == LVForExplicitValue); - assert(oldKind != LVForExplicitType || newKind == LVForExplicitType); - assert(oldKind != LVForExplicitValue || newKind == LVForExplicitValue); - return newKind; +withExplicitVisibilityAlready(LVComputationKind Kind) { + Kind.IgnoreExplicitVisibility = true; + return Kind; } static Optional<Visibility> getExplicitVisibility(const NamedDecl *D, LVComputationKind kind) { - assert(!hasExplicitVisibilityAlready(kind) && + assert(!kind.IgnoreExplicitVisibility && "asking for explicit visibility when we shouldn't be"); - return D->getExplicitVisibility((NamedDecl::ExplicitVisibilityKind) kind); + return D->getExplicitVisibility(kind.getExplicitVisibilityKind()); } /// Is the given declaration a "type" or a "value" for the purposes of @@ -216,30 +213,21 @@ static Optional<Visibility> getVisibilityOf(const NamedDecl *D, return getVisibilityFromAttr(A); } - // If we're on Mac OS X, an 'availability' for Mac OS X attribute - // implies visibility(default). - if (D->getASTContext().getTargetInfo().getTriple().isOSDarwin()) { - for (const auto *A : D->specific_attrs<AvailabilityAttr>()) - if (A->getPlatform()->getName().equals("macos")) - return DefaultVisibility; - } - return None; } -static LinkageInfo -getLVForType(const Type &T, LVComputationKind computation) { - if (computation == LVForLinkageOnly) +LinkageInfo LinkageComputer::getLVForType(const Type &T, + LVComputationKind computation) { + if (computation.IgnoreAllVisibility) return LinkageInfo(T.getLinkage(), DefaultVisibility, true); - return T.getLinkageAndVisibility(); + return getTypeLinkageAndVisibility(&T); } /// \brief Get the most restrictive linkage for the types in the given /// template parameter list. For visibility purposes, template /// parameters are part of the signature of a template. -static LinkageInfo -getLVForTemplateParameterList(const TemplateParameterList *Params, - LVComputationKind computation) { +LinkageInfo LinkageComputer::getLVForTemplateParameterList( + const TemplateParameterList *Params, LVComputationKind computation) { LinkageInfo LV; for (const NamedDecl *P : *Params) { // Template type parameters are the most common and never @@ -264,7 +252,7 @@ getLVForTemplateParameterList(const TemplateParameterList *Params, for (unsigned i = 0, n = NTTP->getNumExpansionTypes(); i != n; ++i) { QualType type = NTTP->getExpansionType(i); if (!type->isDependentType()) - LV.merge(type->getLinkageAndVisibility()); + LV.merge(getTypeLinkageAndVisibility(type)); } continue; } @@ -291,10 +279,6 @@ getLVForTemplateParameterList(const TemplateParameterList *Params, return LV; } -/// getLVForDecl - Get the linkage and visibility for the given declaration. -static LinkageInfo getLVForDecl(const NamedDecl *D, - LVComputationKind computation); - static const Decl *getOutermostFuncOrBlockContext(const Decl *D) { const Decl *Ret = nullptr; const DeclContext *DC = D->getDeclContext(); @@ -311,8 +295,9 @@ static const Decl *getOutermostFuncOrBlockContext(const Decl *D) { /// /// Note that we don't take an LVComputationKind because we always /// want to honor the visibility of template arguments in the same way. -static LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args, - LVComputationKind computation) { +LinkageInfo +LinkageComputer::getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args, + LVComputationKind computation) { LinkageInfo LV; for (const TemplateArgument &Arg : Args) { @@ -334,7 +319,7 @@ static LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args, continue; case TemplateArgument::NullPtr: - LV.merge(Arg.getNullPtrType()->getLinkageAndVisibility()); + LV.merge(getTypeLinkageAndVisibility(Arg.getNullPtrType())); continue; case TemplateArgument::Template: @@ -354,9 +339,9 @@ static LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args, return LV; } -static LinkageInfo -getLVForTemplateArgumentList(const TemplateArgumentList &TArgs, - LVComputationKind computation) { +LinkageInfo +LinkageComputer::getLVForTemplateArgumentList(const TemplateArgumentList &TArgs, + LVComputationKind computation) { return getLVForTemplateArgumentList(TArgs.asArray(), computation); } @@ -379,10 +364,10 @@ static bool shouldConsiderTemplateVisibility(const FunctionDecl *fn, /// LVForValue. /// /// \param[out] LV the computation to use for the parent -static void -mergeTemplateLV(LinkageInfo &LV, const FunctionDecl *fn, - const FunctionTemplateSpecializationInfo *specInfo, - LVComputationKind computation) { +void LinkageComputer::mergeTemplateLV( + LinkageInfo &LV, const FunctionDecl *fn, + const FunctionTemplateSpecializationInfo *specInfo, + LVComputationKind computation) { bool considerVisibility = shouldConsiderTemplateVisibility(fn, specInfo); @@ -402,21 +387,11 @@ mergeTemplateLV(LinkageInfo &LV, const FunctionDecl *fn, /// that would match the given rules? static bool hasDirectVisibilityAttribute(const NamedDecl *D, LVComputationKind computation) { - switch (computation) { - case LVForType: - case LVForExplicitType: - if (D->hasAttr<TypeVisibilityAttr>()) - return true; - // fallthrough - case LVForValue: - case LVForExplicitValue: - if (D->hasAttr<VisibilityAttr>()) - return true; + if (computation.IgnoreAllVisibility) return false; - case LVForLinkageOnly: - return false; - } - llvm_unreachable("bad visibility computation kind"); + + return (computation.isTypeVisibility() && D->hasAttr<TypeVisibilityAttr>()) || + D->hasAttr<VisibilityAttr>(); } /// Should we consider visibility associated with the template @@ -457,9 +432,9 @@ static bool shouldConsiderTemplateVisibility( /// Merge in template-related linkage and visibility for the given /// class template specialization. -static void mergeTemplateLV(LinkageInfo &LV, - const ClassTemplateSpecializationDecl *spec, - LVComputationKind computation) { +void LinkageComputer::mergeTemplateLV( + LinkageInfo &LV, const ClassTemplateSpecializationDecl *spec, + LVComputationKind computation) { bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation); // Merge information from the template parameters, but ignore @@ -509,9 +484,9 @@ static bool shouldConsiderTemplateVisibility( /// Merge in template-related linkage and visibility for the given /// variable template specialization. As usual, follow class template /// specialization logic up to initialization. -static void mergeTemplateLV(LinkageInfo &LV, - const VarTemplateSpecializationDecl *spec, - LVComputationKind computation) { +void LinkageComputer::mergeTemplateLV(LinkageInfo &LV, + const VarTemplateSpecializationDecl *spec, + LVComputationKind computation) { bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation); // Merge information from the template parameters, but ignore @@ -574,6 +549,7 @@ static bool isSingleLineLanguageLinkage(const Decl &D) { } static bool isExportedFromModuleIntefaceUnit(const NamedDecl *D) { + // FIXME: Handle isModulePrivate. switch (D->getModuleOwnershipKind()) { case Decl::ModuleOwnershipKind::Unowned: case Decl::ModuleOwnershipKind::ModulePrivate: @@ -605,14 +581,17 @@ static LinkageInfo getExternalLinkageFor(const NamedDecl *D) { // declaration has module linkage. if (auto *M = D->getOwningModule()) if (M->Kind == Module::ModuleInterfaceUnit) - if (!isExportedFromModuleIntefaceUnit(D)) + if (!isExportedFromModuleIntefaceUnit( + cast<NamedDecl>(D->getCanonicalDecl()))) return LinkageInfo(ModuleLinkage, DefaultVisibility, false); return LinkageInfo::external(); } -static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, - LVComputationKind computation) { +LinkageInfo +LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, + LVComputationKind computation, + bool IgnoreVarTypeLinkage) { assert(D->getDeclContext()->getRedeclContext()->isFileContext() && "Not a name having namespace scope"); ASTContext &Context = D->getASTContext(); @@ -652,7 +631,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, PrevVar = PrevVar->getPreviousDecl()) { if (PrevVar->getStorageClass() == SC_PrivateExtern && Var->getStorageClass() == SC_None) - return PrevVar->getLinkageAndVisibility(); + return getDeclLinkageAndVisibility(PrevVar); // Explicitly declared static. if (PrevVar->getStorageClass() == SC_Static) return getInternalLinkageFor(Var); @@ -669,23 +648,23 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // - a data member of an anonymous union. const VarDecl *VD = IFD->getVarDecl(); assert(VD && "Expected a VarDecl in this IndirectFieldDecl!"); - return getLVForNamespaceScopeDecl(VD, computation); + return getLVForNamespaceScopeDecl(VD, computation, IgnoreVarTypeLinkage); } assert(!isa<FieldDecl>(D) && "Didn't expect a FieldDecl!"); if (D->isInAnonymousNamespace()) { 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 (including those inside extern "C" contexts) internal - // linkage, not unique external linkage: + // FIXME: The check for extern "C" here is not justified by the standard + // wording, but we retain it from the pre-DR1113 model to avoid breaking + // code. // // 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(); + return getInternalLinkageFor(D); } // Set up the defaults. @@ -694,7 +673,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // If the declaration of an identifier for an object has file // scope and no storage-class specifier, its linkage is // external. - LinkageInfo LV; + LinkageInfo LV = getExternalLinkageFor(D); if (!hasExplicitVisibilityAlready(computation)) { if (Optional<Visibility> Vis = getExplicitVisibility(D, computation)) { @@ -717,13 +696,10 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // Add in global settings if the above didn't give us direct visibility. if (!LV.isVisibilityExplicit()) { // Use global type/value visibility as appropriate. - Visibility globalVisibility; - if (computation == LVForValue) { - globalVisibility = Context.getLangOpts().getValueVisibilityMode(); - } else { - assert(computation == LVForType); - globalVisibility = Context.getLangOpts().getTypeVisibilityMode(); - } + Visibility globalVisibility = + computation.isValueVisibility() + ? Context.getLangOpts().getValueVisibilityMode() + : Context.getLangOpts().getTypeVisibilityMode(); LV.mergeVisibility(globalVisibility, /*explicit*/ false); // If we're paying attention to global visibility, apply @@ -761,10 +737,10 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // // Note that we don't want to make the variable non-external // because of this, but unique-external linkage suits us. - if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var)) { + if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var) && + !IgnoreVarTypeLinkage) { LinkageInfo TypeLV = getLVForType(*Var->getType(), computation); - if (TypeLV.getLinkage() != ExternalLinkage && - TypeLV.getLinkage() != ModuleLinkage) + if (!isExternallyVisible(TypeLV.getLinkage())) return LinkageInfo::uniqueExternal(); if (!LV.isVisibilityExplicit()) LV.mergeVisibility(TypeLV); @@ -802,19 +778,13 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // unique-external linkage, it's not legally usable from outside // this translation unit. However, we should use the C linkage // rules instead for extern "C" declarations. - if (Context.getLangOpts().CPlusPlus && - !Function->isInExternCContext()) { - // Only look at the type-as-written. If this function has an auto-deduced - // return type, we can't compute the linkage of that type because it could - // require looking at the linkage of this function, and we don't need this - // for correctness because the type is not part of the function's - // signature. - // FIXME: This is a hack. We should be able to solve this circularity and - // the one in getLVForClassMember for Functions some other way. + if (Context.getLangOpts().CPlusPlus && !Function->isInExternCContext()) { + // Only look at the type-as-written. Otherwise, deducing the return type + // of a function could change its linkage. QualType TypeAsWritten = Function->getType(); if (TypeSourceInfo *TSI = Function->getTypeSourceInfo()) TypeAsWritten = TSI->getType(); - if (TypeAsWritten->getLinkage() == UniqueExternalLinkage) + if (!isExternallyVisible(TypeAsWritten->getLinkage())) return LinkageInfo::uniqueExternal(); } @@ -883,16 +853,18 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, return LinkageInfo::none(); } - // If we ended up with non-external linkage, visibility should + // If we ended up with non-externally-visible linkage, visibility should // always be default. - if (LV.getLinkage() != ExternalLinkage) + if (!isExternallyVisible(LV.getLinkage())) return LinkageInfo(LV.getLinkage(), DefaultVisibility, false); return LV; } -static LinkageInfo getLVForClassMember(const NamedDecl *D, - LVComputationKind computation) { +LinkageInfo +LinkageComputer::getLVForClassMember(const NamedDecl *D, + LVComputationKind computation, + bool IgnoreVarTypeLinkage) { // Only certain class members have linkage. Note that fields don't // really have linkage, but it's convenient to say they do for the // purposes of calculating linkage of pointer-to-data-member @@ -935,12 +907,11 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LinkageInfo classLV = getLVForDecl(cast<RecordDecl>(D->getDeclContext()), classComputation); - // If the class already has unique-external linkage, we can't improve. - if (classLV.getLinkage() == UniqueExternalLinkage) - return LinkageInfo::uniqueExternal(); - + // The member has the same linkage as the class. If that's not externally + // visible, we don't need to compute anything about the linkage. + // FIXME: If we're only computing linkage, can we bail out here? if (!isExternallyVisible(classLV.getLinkage())) - return LinkageInfo::none(); + return classLV; // Otherwise, don't merge in classLV yet, because in certain cases @@ -950,22 +921,14 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, const NamedDecl *explicitSpecSuppressor = nullptr; if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) { - // If the type of the function uses a type with unique-external - // linkage, it's not legally usable from outside this translation unit. - // But only look at the type-as-written. If this function has an - // auto-deduced return type, we can't compute the linkage of that type - // because it could require looking at the linkage of this function, and we - // don't need this for correctness because the type is not part of the - // function's signature. - // FIXME: This is a hack. We should be able to solve this circularity and - // the one in getLVForNamespaceScopeDecl for Functions some other way. - { - QualType TypeAsWritten = MD->getType(); - if (TypeSourceInfo *TSI = MD->getTypeSourceInfo()) - TypeAsWritten = TSI->getType(); - if (TypeAsWritten->getLinkage() == UniqueExternalLinkage) - return LinkageInfo::uniqueExternal(); - } + // Only look at the type-as-written. Otherwise, deducing the return type + // of a function could change its linkage. + QualType TypeAsWritten = MD->getType(); + if (TypeSourceInfo *TSI = MD->getTypeSourceInfo()) + TypeAsWritten = TSI->getType(); + if (!isExternallyVisible(TypeAsWritten->getLinkage())) + return LinkageInfo::uniqueExternal(); + // If this is a method template specialization, use the linkage for // the template parameters and arguments. if (FunctionTemplateSpecializationInfo *spec @@ -1002,10 +965,14 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, // Modify the variable's linkage by its type, but ignore the // type's visibility unless it's a definition. - LinkageInfo typeLV = getLVForType(*VD->getType(), computation); - if (!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit()) - LV.mergeVisibility(typeLV); - LV.mergeExternalVisibility(typeLV); + if (!IgnoreVarTypeLinkage) { + LinkageInfo typeLV = getLVForType(*VD->getType(), computation); + // FIXME: If the type's linkage is not externally visible, we can + // give this static data member UniqueExternalLinkage. + if (!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit()) + LV.mergeVisibility(typeLV); + LV.mergeExternalVisibility(typeLV); + } if (isExplicitMemberSpecialization(VD)) { explicitSpecSuppressor = VD; @@ -1047,17 +1014,16 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, return LV; } -void NamedDecl::anchor() { } - -static LinkageInfo computeLVForDecl(const NamedDecl *D, - LVComputationKind computation); +void NamedDecl::anchor() {} bool NamedDecl::isLinkageValid() const { if (!hasCachedLinkage()) return true; - return computeLVForDecl(this, LVForLinkageOnly).getLinkage() == - getCachedLinkage(); + Linkage L = LinkageComputer{} + .computeLVForDecl(this, LVComputationKind::forLinkageOnly()) + .getLinkage(); + return L == getCachedLinkage(); } ObjCStringFormatFamily NamedDecl::getObjCFStringFormattingFamily() const { @@ -1076,13 +1042,13 @@ ObjCStringFormatFamily NamedDecl::getObjCFStringFormattingFamily() const { Linkage NamedDecl::getLinkageInternal() const { // We don't care about visibility here, so ask for the cheapest // possible visibility analysis. - return getLVForDecl(this, LVForLinkageOnly).getLinkage(); + return LinkageComputer{} + .getLVForDecl(this, LVComputationKind::forLinkageOnly()) + .getLinkage(); } LinkageInfo NamedDecl::getLinkageAndVisibility() const { - LVComputationKind computation = - (usesTypeVisibility(this) ? LVForType : LVForValue); - return getLVForDecl(this, computation); + return LinkageComputer{}.getDeclLinkageAndVisibility(this); } static Optional<Visibility> @@ -1160,30 +1126,46 @@ NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const { return getExplicitVisibilityAux(this, kind, false); } -static LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl, - LVComputationKind computation) { +LinkageInfo LinkageComputer::getLVForClosure(const DeclContext *DC, + Decl *ContextDecl, + LVComputationKind computation) { // This lambda has its linkage/visibility determined by its owner. - if (ContextDecl) { - if (isa<ParmVarDecl>(ContextDecl)) - DC = ContextDecl->getDeclContext()->getRedeclContext(); - else - return getLVForDecl(cast<NamedDecl>(ContextDecl), computation); - } + const NamedDecl *Owner; + if (!ContextDecl) + Owner = dyn_cast<NamedDecl>(DC); + else if (isa<ParmVarDecl>(ContextDecl)) + Owner = + dyn_cast<NamedDecl>(ContextDecl->getDeclContext()->getRedeclContext()); + else + Owner = cast<NamedDecl>(ContextDecl); - if (const auto *ND = dyn_cast<NamedDecl>(DC)) - return getLVForDecl(ND, computation); + if (!Owner) + return LinkageInfo::none(); - // FIXME: We have a closure at TU scope with no context declaration. This - // should probably have no linkage. - return LinkageInfo::external(); + // If the owner has a deduced type, we need to skip querying the linkage and + // visibility of that type, because it might involve this closure type. The + // only effect of this is that we might give a lambda VisibleNoLinkage rather + // than NoLinkage when we don't strictly need to, which is benign. + auto *VD = dyn_cast<VarDecl>(Owner); + LinkageInfo OwnerLV = + VD && VD->getType()->getContainedDeducedType() + ? computeLVForDecl(Owner, computation, /*IgnoreVarTypeLinkage*/true) + : getLVForDecl(Owner, computation); + + // A lambda never formally has linkage. But if the owner is externally + // visible, then the lambda is too. We apply the same rules to blocks. + if (!isExternallyVisible(OwnerLV.getLinkage())) + return LinkageInfo::none(); + return LinkageInfo(VisibleNoLinkage, OwnerLV.getVisibility(), + OwnerLV.isVisibilityExplicit()); } -static LinkageInfo getLVForLocalDecl(const NamedDecl *D, - LVComputationKind computation) { +LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D, + LVComputationKind computation) { if (const auto *Function = dyn_cast<FunctionDecl>(D)) { if (Function->isInAnonymousNamespace() && !Function->isInExternCContext()) - return LinkageInfo::uniqueExternal(); + return getInternalLinkageFor(Function); // This is a "void f();" which got merged with a file static. if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) @@ -1206,7 +1188,7 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D, if (const auto *Var = dyn_cast<VarDecl>(D)) { if (Var->hasExternalStorage()) { if (Var->isInAnonymousNamespace() && !Var->isInExternCContext()) - return LinkageInfo::uniqueExternal(); + return getInternalLinkageFor(Var); LinkageInfo LV; if (Var->getStorageClass() == SC_PrivateExtern) @@ -1272,8 +1254,9 @@ getOutermostEnclosingLambda(const CXXRecordDecl *Record) { return Ret; } -static LinkageInfo computeLVForDecl(const NamedDecl *D, - LVComputationKind computation) { +LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D, + LVComputationKind computation, + bool IgnoreVarTypeLinkage) { // Internal_linkage attribute overrides other considerations. if (D->hasAttr<InternalLinkageAttr>()) return getInternalLinkageFor(D); @@ -1361,7 +1344,7 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D, // Handle linkage for namespace-scope names. if (D->getDeclContext()->getRedeclContext()->isFileContext()) - return getLVForNamespaceScopeDecl(D, computation); + return getLVForNamespaceScopeDecl(D, computation, IgnoreVarTypeLinkage); // C++ [basic.link]p5: // In addition, a member function, static data member, a named @@ -1371,7 +1354,7 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D, // purposes (7.1.3), has external linkage if the name of the class // has external linkage. if (D->getDeclContext()->isRecord()) - return getLVForClassMember(D, computation); + return getLVForClassMember(D, computation, IgnoreVarTypeLinkage); // C++ [basic.link]p6: // The name of a function declared in block scope and the name of @@ -1392,56 +1375,93 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D, return LinkageInfo::none(); } -namespace clang { -class LinkageComputer { -public: - static LinkageInfo getLVForDecl(const NamedDecl *D, - LVComputationKind computation) { - // Internal_linkage attribute overrides other considerations. - if (D->hasAttr<InternalLinkageAttr>()) - return getInternalLinkageFor(D); +/// getLVForDecl - Get the linkage and visibility for the given declaration. +LinkageInfo LinkageComputer::getLVForDecl(const NamedDecl *D, + LVComputationKind computation) { + // Internal_linkage attribute overrides other considerations. + if (D->hasAttr<InternalLinkageAttr>()) + return getInternalLinkageFor(D); + + if (computation.IgnoreAllVisibility && D->hasCachedLinkage()) + return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false); - if (computation == LVForLinkageOnly && D->hasCachedLinkage()) - return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false); + if (llvm::Optional<LinkageInfo> LI = lookup(D, computation)) + return *LI; - LinkageInfo LV = computeLVForDecl(D, computation); - if (D->hasCachedLinkage()) - assert(D->getCachedLinkage() == LV.getLinkage()); + LinkageInfo LV = computeLVForDecl(D, computation); + if (D->hasCachedLinkage()) + assert(D->getCachedLinkage() == LV.getLinkage()); - D->setCachedLinkage(LV.getLinkage()); + D->setCachedLinkage(LV.getLinkage()); + cache(D, computation, LV); #ifndef NDEBUG - // In C (because of gnu inline) and in c++ with microsoft extensions an - // static can follow an extern, so we can have two decls with different - // linkages. - const LangOptions &Opts = D->getASTContext().getLangOpts(); - if (!Opts.CPlusPlus || Opts.MicrosoftExt) - return LV; + // In C (because of gnu inline) and in c++ with microsoft extensions an + // static can follow an extern, so we can have two decls with different + // linkages. + const LangOptions &Opts = D->getASTContext().getLangOpts(); + if (!Opts.CPlusPlus || Opts.MicrosoftExt) + return LV; - // We have just computed the linkage for this decl. By induction we know - // that all other computed linkages match, check that the one we just - // computed also does. - NamedDecl *Old = nullptr; - for (auto I : D->redecls()) { - auto *T = cast<NamedDecl>(I); - if (T == D) - continue; - if (!T->isInvalidDecl() && T->hasCachedLinkage()) { - Old = T; - break; - } + // We have just computed the linkage for this decl. By induction we know + // that all other computed linkages match, check that the one we just + // computed also does. + NamedDecl *Old = nullptr; + for (auto I : D->redecls()) { + auto *T = cast<NamedDecl>(I); + if (T == D) + continue; + if (!T->isInvalidDecl() && T->hasCachedLinkage()) { + Old = T; + break; } - assert(!Old || Old->getCachedLinkage() == D->getCachedLinkage()); + } + assert(!Old || Old->getCachedLinkage() == D->getCachedLinkage()); #endif - return LV; - } -}; + return LV; } -static LinkageInfo getLVForDecl(const NamedDecl *D, - LVComputationKind computation) { - return clang::LinkageComputer::getLVForDecl(D, computation); +LinkageInfo LinkageComputer::getDeclLinkageAndVisibility(const NamedDecl *D) { + return getLVForDecl(D, + LVComputationKind(usesTypeVisibility(D) + ? NamedDecl::VisibilityForType + : NamedDecl::VisibilityForValue)); +} + +Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const { + Module *M = getOwningModule(); + if (!M) + return nullptr; + + switch (M->Kind) { + case Module::ModuleMapModule: + // Module map modules have no special linkage semantics. + return nullptr; + + case Module::ModuleInterfaceUnit: + return M; + + case Module::GlobalModuleFragment: { + // External linkage declarations in the global module have no owning module + // for linkage purposes. But internal linkage declarations in the global + // module fragment of a particular module are owned by that module for + // linkage purposes. + if (IgnoreLinkage) + return nullptr; + bool InternalLinkage; + if (auto *ND = dyn_cast<NamedDecl>(this)) + InternalLinkage = !ND->hasExternalFormalLinkage(); + else { + auto *NSD = dyn_cast<NamespaceDecl>(this); + InternalLinkage = (NSD && NSD->isAnonymousNamespace()) || + isInAnonymousNamespace(); + } + return InternalLinkage ? M->Parent : nullptr; + } + } + + llvm_unreachable("unknown module kind"); } void NamedDecl::printName(raw_ostream &os) const { @@ -1473,7 +1493,7 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, return; } - typedef SmallVector<const DeclContext *, 8> ContextsTy; + using ContextsTy = SmallVector<const DeclContext *, 8>; ContextsTy Contexts; // Collect contexts. @@ -1482,12 +1502,11 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, Ctx = Ctx->getParent(); } - for (const DeclContext *DC : reverse(Contexts)) { + for (const DeclContext *DC : llvm::reverse(Contexts)) { if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC)) { OS << Spec->getName(); const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - TemplateSpecializationType::PrintTemplateArgumentList( - OS, TemplateArgs.asArray(), P); + printTemplateArgumentList(OS, TemplateArgs.asArray(), P); } else if (const auto *ND = dyn_cast<NamespaceDecl>(DC)) { if (P.SuppressUnwrittenScope && (ND->isAnonymousNamespace() || ND->isInline())) @@ -1612,14 +1631,6 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const { cast<UnresolvedUsingValueDecl>(OldD)->getQualifier()); } - // UsingDirectiveDecl's are not really NamedDecl's, and all have same name. - // They can be replaced if they nominate the same namespace. - // FIXME: Is this true even if they have different module visibility? - if (auto *UD = dyn_cast<UsingDirectiveDecl>(this)) - return UD->getNominatedNamespace()->getOriginalNamespace() == - cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace() - ->getOriginalNamespace(); - if (isRedeclarable(getKind())) { if (getCanonicalDecl() != OldD->getCanonicalDecl()) return false; @@ -1754,11 +1765,9 @@ SourceLocation DeclaratorDecl::getOuterLocStart() const { return getTemplateOrInnerLocStart(this); } -namespace { - // Helper function: returns true if QT is or contains a type // having a postfix component. -bool typeIsPostfix(clang::QualType QT) { +static bool typeIsPostfix(QualType QT) { while (true) { const Type* T = QT.getTypePtr(); switch (T->getTypeClass()) { @@ -1792,8 +1801,6 @@ bool typeIsPostfix(clang::QualType QT) { } } -} // namespace - SourceRange DeclaratorDecl::getSourceRange() const { SourceLocation RangeEnd = getLocation(); if (TypeSourceInfo *TInfo = getTypeSourceInfo()) { @@ -1843,7 +1850,7 @@ VarDecl::VarDecl(Kind DK, ASTContext &C, DeclContext *DC, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass SC) : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), - redeclarable_base(C), Init() { + redeclarable_base(C) { static_assert(sizeof(VarDeclBitfields) <= sizeof(unsigned), "VarDeclBitfields too large!"); static_assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned), @@ -1967,6 +1974,9 @@ VarDecl *VarDecl::getCanonicalDecl() { return getFirstDecl(); } VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition(ASTContext &C) const { + if (isThisDeclarationADemotedDefinition()) + return DeclarationOnly; + // C++ [basic.def]p2: // A declaration is a definition unless [...] it contains the 'extern' // specifier or a linkage-specification and neither an initializer [...], @@ -1980,9 +1990,6 @@ VarDecl::isThisDeclarationADefinition(ASTContext &C) const { // // FIXME: How do you declare (but not define) a partial specialization of // a static data member template outside the containing class? - if (isThisDeclarationADemotedDefinition()) - return DeclarationOnly; - if (isStaticDataMember()) { if (isOutOfLine() && !(getCanonicalDecl()->isInline() && @@ -2022,9 +2029,12 @@ VarDecl::isThisDeclarationADefinition(ASTContext &C) const { // A variable template specialization (other than a static data member // template or an explicit specialization) is a declaration until we // instantiate its initializer. - if (isa<VarTemplateSpecializationDecl>(this) && - getTemplateSpecializationKind() != TSK_ExplicitSpecialization) - return DeclarationOnly; + if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(this)) { + if (VTSD->getTemplateSpecializationKind() != TSK_ExplicitSpecialization && + !isa<VarTemplatePartialSpecializationDecl>(VTSD) && + !VTSD->IsCompleteDefinition) + return DeclarationOnly; + } if (hasExternalStorage()) return DeclarationOnly; @@ -2408,15 +2418,21 @@ void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK, dyn_cast<VarTemplateSpecializationDecl>(this)) { Spec->setSpecializationKind(TSK); if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() && - Spec->getPointOfInstantiation().isInvalid()) + Spec->getPointOfInstantiation().isInvalid()) { Spec->setPointOfInstantiation(PointOfInstantiation); + if (ASTMutationListener *L = getASTContext().getASTMutationListener()) + L->InstantiationRequested(this); + } } if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) { MSI->setTemplateSpecializationKind(TSK); if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() && - MSI->getPointOfInstantiation().isInvalid()) + MSI->getPointOfInstantiation().isInvalid()) { MSI->setPointOfInstantiation(PointOfInstantiation); + if (ASTMutationListener *L = getASTContext().getASTMutationListener()) + L->InstantiationRequested(this); + } } } @@ -2548,8 +2564,7 @@ void FunctionDecl::getNameForDiagnostic( NamedDecl::getNameForDiagnostic(OS, Policy, Qualified); const TemplateArgumentList *TemplateArgs = getTemplateSpecializationArgs(); if (TemplateArgs) - TemplateSpecializationType::PrintTemplateArgumentList( - OS, TemplateArgs->asArray(), Policy); + printTemplateArgumentList(OS, TemplateArgs->asArray(), Policy); } bool FunctionDecl::isVariadic() const { @@ -2747,6 +2762,20 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction(bool *IsAligned) const return Params == FPT->getNumParams(); } +bool FunctionDecl::isDestroyingOperatorDelete() const { + // C++ P0722: + // Within a class C, a single object deallocation function with signature + // (T, std::destroying_delete_t, <more params>) + // is a destroying operator delete. + if (!isa<CXXMethodDecl>(this) || getOverloadedOperator() != OO_Delete || + getNumParams() < 2) + return false; + + auto *RD = getParamDecl(1)->getType()->getAsCXXRecordDecl(); + return RD && RD->isInStdNamespace() && RD->getIdentifier() && + RD->getIdentifier()->isStr("destroying_delete_t"); +} + LanguageLinkage FunctionDecl::getLanguageLinkage() const { return getDeclLanguageLinkage(*this); } @@ -2871,7 +2900,6 @@ unsigned FunctionDecl::getBuiltinID() const { return BuiltinID; } - /// getNumParams - Return the number of parameters this function must have /// based on its FunctionType. This is the length of the ParamInfo array /// after it has been created. @@ -3057,7 +3085,8 @@ SourceRange FunctionDecl::getExceptionSpecSourceRange() const { const Attr *FunctionDecl::getUnusedResultAttr() const { QualType RetType = getReturnType(); if (RetType->isRecordType()) { - if (const CXXRecordDecl *Ret = RetType->getAsCXXRecordDecl()) { + if (const auto *Ret = + dyn_cast_or_null<RecordDecl>(RetType->getAsTagDecl())) { if (const auto *R = Ret->getAttr<WarnUnusedResultAttr>()) return R; } @@ -3382,7 +3411,6 @@ DependentFunctionTemplateSpecializationInfo:: DependentFunctionTemplateSpecializationInfo(const UnresolvedSetImpl &Ts, const TemplateArgumentListInfo &TArgs) : AngleLocs(TArgs.getLAngleLoc(), TArgs.getRAngleLoc()) { - NumTemplates = Ts.size(); NumArgs = TArgs.size(); @@ -3420,15 +3448,21 @@ FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK, FTSInfo->setTemplateSpecializationKind(TSK); if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() && - FTSInfo->getPointOfInstantiation().isInvalid()) + FTSInfo->getPointOfInstantiation().isInvalid()) { FTSInfo->setPointOfInstantiation(PointOfInstantiation); + if (ASTMutationListener *L = getASTContext().getASTMutationListener()) + L->InstantiationRequested(this); + } } else if (MemberSpecializationInfo *MSInfo = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>()) { MSInfo->setTemplateSpecializationKind(TSK); if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() && - MSInfo->getPointOfInstantiation().isInvalid()) + MSInfo->getPointOfInstantiation().isInvalid()) { MSInfo->setPointOfInstantiation(PointOfInstantiation); + if (ASTMutationListener *L = getASTContext().getASTMutationListener()) + L->InstantiationRequested(this); + } } else llvm_unreachable("Function cannot have a template specialization kind"); } @@ -3598,8 +3632,7 @@ bool FieldDecl::isAnonymousStructOrUnion() const { unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const { assert(isBitField() && "not a bitfield"); - auto *BitWidth = static_cast<Expr *>(InitStorage.getPointer()); - return BitWidth->EvaluateKnownConstInt(Ctx).getZExtValue(); + return getBitWidth()->EvaluateKnownConstInt(Ctx).getZExtValue(); } unsigned FieldDecl::getFieldIndex() const { @@ -3610,7 +3643,8 @@ unsigned FieldDecl::getFieldIndex() const { if (CachedFieldIndex) return CachedFieldIndex - 1; unsigned Index = 0; - const RecordDecl *RD = getParent(); + const RecordDecl *RD = getParent()->getDefinition(); + assert(RD && "requested index for field of struct with no definition"); for (auto *Field : RD->fields()) { Field->getCanonicalDecl()->CachedFieldIndex = Index + 1; @@ -3622,25 +3656,18 @@ unsigned FieldDecl::getFieldIndex() const { } SourceRange FieldDecl::getSourceRange() const { - switch (InitStorage.getInt()) { - // All three of these cases store an optional Expr*. - case ISK_BitWidthOrNothing: - case ISK_InClassCopyInit: - case ISK_InClassListInit: - if (const auto *E = static_cast<const Expr *>(InitStorage.getPointer())) - return SourceRange(getInnerLocStart(), E->getLocEnd()); - // FALLTHROUGH - - case ISK_CapturedVLAType: - return DeclaratorDecl::getSourceRange(); - } - llvm_unreachable("bad init storage kind"); + const Expr *FinalExpr = getInClassInitializer(); + if (!FinalExpr) + FinalExpr = getBitWidth(); + if (FinalExpr) + return SourceRange(getInnerLocStart(), FinalExpr->getLocEnd()); + return DeclaratorDecl::getSourceRange(); } void FieldDecl::setCapturedVLAType(const VariableArrayType *VLAType) { assert((getParent()->isLambda() || getParent()->isCapturedRecord()) && "capturing type in non-lambda or captured record."); - assert(InitStorage.getInt() == ISK_BitWidthOrNothing && + assert(InitStorage.getInt() == ISK_NoInit && InitStorage.getPointer() == nullptr && "bit width, initializer or captured type already set"); InitStorage.setPointerAndInt(const_cast<VariableArrayType *>(VLAType), @@ -3753,7 +3780,7 @@ void TagDecl::setTemplateParameterListsInfo( // EnumDecl Implementation //===----------------------------------------------------------------------===// -void EnumDecl::anchor() { } +void EnumDecl::anchor() {} EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, @@ -3862,12 +3889,10 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, RecordDecl *PrevDecl) - : TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc) { - HasFlexibleArrayMember = false; - AnonymousStructOrUnion = false; - HasObjectMember = false; - HasVolatileMember = false; - LoadedFieldsFromExternalStorage = false; + : TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc), + HasFlexibleArrayMember(false), AnonymousStructOrUnion(false), + HasObjectMember(false), HasVolatileMember(false), + LoadedFieldsFromExternalStorage(false) { assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!"); } @@ -3958,9 +3983,9 @@ void RecordDecl::LoadFieldsFromExternalStorage() const { bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const { ASTContext &Context = getASTContext(); - if (!Context.getLangOpts().Sanitize.hasOneOf( - SanitizerKind::Address | SanitizerKind::KernelAddress) || - !Context.getLangOpts().SanitizeAddressFieldPadding) + const SanitizerMask EnabledAsanMask = Context.getLangOpts().Sanitize.Mask & + (SanitizerKind::Address | SanitizerKind::KernelAddress); + if (!EnabledAsanMask || !Context.getLangOpts().SanitizeAddressFieldPadding) return false; const auto &Blacklist = Context.getSanitizerBlacklist(); const auto *CXXRD = dyn_cast<CXXRecordDecl>(this); @@ -3978,9 +4003,11 @@ bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const { ReasonToReject = 4; // has trivial destructor. else if (CXXRD->isStandardLayout()) ReasonToReject = 5; // is standard layout. - else if (Blacklist.isBlacklistedLocation(getLocation(), "field-padding")) + else if (Blacklist.isBlacklistedLocation(EnabledAsanMask, getLocation(), + "field-padding")) ReasonToReject = 6; // is in a blacklisted file. - else if (Blacklist.isBlacklistedType(getQualifiedNameAsString(), + else if (Blacklist.isBlacklistedType(EnabledAsanMask, + getQualifiedNameAsString(), "field-padding")) ReasonToReject = 7; // is blacklisted. @@ -4014,7 +4041,6 @@ const FieldDecl *RecordDecl::findFirstNamedDataMember() const { return nullptr; } - //===----------------------------------------------------------------------===// // BlockDecl Implementation //===----------------------------------------------------------------------===// @@ -4060,13 +4086,13 @@ SourceRange BlockDecl::getSourceRange() const { // Other Decl Allocation/Deallocation Method Implementations //===----------------------------------------------------------------------===// -void TranslationUnitDecl::anchor() { } +void TranslationUnitDecl::anchor() {} TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) { return new (C, (DeclContext *)nullptr) TranslationUnitDecl(C); } -void PragmaCommentDecl::anchor() { } +void PragmaCommentDecl::anchor() {} PragmaCommentDecl *PragmaCommentDecl::Create(const ASTContext &C, TranslationUnitDecl *DC, @@ -4088,7 +4114,7 @@ PragmaCommentDecl *PragmaCommentDecl::CreateDeserialized(ASTContext &C, PragmaCommentDecl(nullptr, SourceLocation(), PCK_Unknown); } -void PragmaDetectMismatchDecl::anchor() { } +void PragmaDetectMismatchDecl::anchor() {} PragmaDetectMismatchDecl * PragmaDetectMismatchDecl::Create(const ASTContext &C, TranslationUnitDecl *DC, @@ -4113,14 +4139,14 @@ PragmaDetectMismatchDecl::CreateDeserialized(ASTContext &C, unsigned ID, PragmaDetectMismatchDecl(nullptr, SourceLocation(), 0); } -void ExternCContextDecl::anchor() { } +void ExternCContextDecl::anchor() {} ExternCContextDecl *ExternCContextDecl::Create(const ASTContext &C, TranslationUnitDecl *DC) { return new (C, DC) ExternCContextDecl(DC); } -void LabelDecl::anchor() { } +void LabelDecl::anchor() {} LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II) { @@ -4146,7 +4172,7 @@ void LabelDecl::setMSAsmLabel(StringRef Name) { MSAsmName = Buffer; } -void ValueDecl::anchor() { } +void ValueDecl::anchor() {} bool ValueDecl::isWeak() const { for (const auto *I : attrs()) @@ -4156,7 +4182,7 @@ bool ValueDecl::isWeak() const { return isWeakImported(); } -void ImplicitParamDecl::anchor() { } +void ImplicitParamDecl::anchor() {} ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, @@ -4239,7 +4265,7 @@ EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) { QualType(), nullptr, llvm::APSInt()); } -void IndirectFieldDecl::anchor() { } +void IndirectFieldDecl::anchor() {} IndirectFieldDecl::IndirectFieldDecl(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName N, @@ -4273,7 +4299,7 @@ SourceRange EnumConstantDecl::getSourceRange() const { return SourceRange(getLocation(), End); } -void TypeDecl::anchor() { } +void TypeDecl::anchor() {} TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, @@ -4281,7 +4307,7 @@ TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC, return new (C, DC) TypedefDecl(C, DC, StartLoc, IdLoc, Id, TInfo); } -void TypedefNameDecl::anchor() { } +void TypedefNameDecl::anchor() {} TagDecl *TypedefNameDecl::getAnonDeclWithTypedefName(bool AnyRedecl) const { if (auto *TT = getTypeSourceInfo()->getType()->getAs<TagType>()) { @@ -4355,7 +4381,7 @@ SourceRange TypeAliasDecl::getSourceRange() const { return SourceRange(getLocStart(), RangeEnd); } -void FileScopeAsmDecl::anchor() { } +void FileScopeAsmDecl::anchor() {} FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC, StringLiteral *Str, @@ -4398,9 +4424,7 @@ static unsigned getNumModuleIdentifiers(Module *Mod) { ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported, ArrayRef<SourceLocation> IdentifierLocs) - : Decl(Import, DC, StartLoc), ImportedAndComplete(Imported, true), - NextLocalImport() -{ + : Decl(Import, DC, StartLoc), ImportedAndComplete(Imported, true) { assert(getNumModuleIdentifiers(Imported) == IdentifierLocs.size()); auto *StoredLocs = getTrailingObjects<SourceLocation>(); std::uninitialized_copy(IdentifierLocs.begin(), IdentifierLocs.end(), @@ -4409,9 +4433,7 @@ ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc, ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported, SourceLocation EndLoc) - : Decl(Import, DC, StartLoc), ImportedAndComplete(Imported, false), - NextLocalImport() -{ + : Decl(Import, DC, StartLoc), ImportedAndComplete(Imported, false) { *getTrailingObjects<SourceLocation>() = EndLoc; } diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index cd2c83a02f59..29ce7ae034b5 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -1,4 +1,4 @@ -//===--- DeclBase.cpp - Declaration AST Node Implementation ---------------===// +//===- DeclBase.cpp - Declaration AST Node Implementation -----------------===// // // The LLVM Compiler Infrastructure // @@ -15,6 +15,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/Attr.h" +#include "clang/AST/AttrIterator.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclContextInternals.h" @@ -25,11 +26,30 @@ #include "clang/AST/DependentDiagnostic.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/Stmt.h" -#include "clang/AST/StmtCXX.h" #include "clang/AST/Type.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/ObjCRuntime.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Basic/VersionTuple.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> +#include <cassert> +#include <cstddef> +#include <string> +#include <tuple> +#include <utility> + using namespace clang; //===----------------------------------------------------------------------===// @@ -74,8 +94,9 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Ctx, DeclContext *Parent, std::size_t Extra) { assert(!Parent || &Parent->getParentASTContext() == &Ctx); // With local visibility enabled, we track the owning module even for local - // declarations. - if (Ctx.getLangOpts().trackLocalOwningModule()) { + // declarations. We create the TU decl early and may not yet know what the + // LangOpts are, so conservatively allocate the storage. + if (Ctx.getLangOpts().trackLocalOwningModule() || !Parent) { // Ensure required alignment of the resulting object by adding extra // padding at the start if required. size_t ExtraAlign = @@ -229,7 +250,6 @@ const DeclContext *Decl::getParentFunctionOrMethod() const { return nullptr; } - //===----------------------------------------------------------------------===// // PrettyStackTraceDecl Implementation //===----------------------------------------------------------------------===// @@ -259,7 +279,7 @@ void PrettyStackTraceDecl::print(raw_ostream &OS) const { //===----------------------------------------------------------------------===// // Out-of-line virtual method providing a home for Decl. -Decl::~Decl() { } +Decl::~Decl() = default; void Decl::setDeclContext(DeclContext *DC) { DeclCtx = DC; @@ -314,12 +334,11 @@ bool Decl::isLexicallyWithinFunctionOrMethod() const { } bool Decl::isInAnonymousNamespace() const { - const DeclContext *DC = getDeclContext(); - do { + for (const DeclContext *DC = getDeclContext(); DC; DC = DC->getParent()) { if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC)) if (ND->isAnonymousNamespace()) return true; - } while ((DC = DC->getParent())); + } return false; } @@ -680,7 +699,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case CXXConversion: case EnumConstant: case Var: - case Binding: case ImplicitParam: case ParmVar: case ObjCMethod: @@ -692,10 +710,11 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case IndirectField: return IDNS_Ordinary | IDNS_Member; + case Binding: case NonTypeTemplateParm: - // Non-type template parameters are not found by lookups that ignore - // non-types, but they are found by redeclaration lookups for tag types, - // so we include them in the tag namespace. + case VarTemplate: + // These (C++-only) declarations are found by redeclaration lookup for + // tag types, so we include them in the tag namespace. return IDNS_Ordinary | IDNS_Tag; case ObjCCompatibleAlias: @@ -704,7 +723,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case Typedef: case TypeAlias: - case TypeAliasTemplate: case TemplateTypeParm: case ObjCTypeParam: return IDNS_Ordinary | IDNS_Type; @@ -740,11 +758,11 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { return IDNS_Namespace; case FunctionTemplate: - case VarTemplate: return IDNS_Ordinary; case ClassTemplate: case TemplateTemplateParm: + case TypeAliasTemplate: return IDNS_Ordinary | IDNS_Tag | IDNS_Type; case OMPDeclareReduction: @@ -914,7 +932,6 @@ const FunctionType *Decl::getFunctionType(bool BlocksToo) const { return Ty->getAs<FunctionType>(); } - /// Starting at a given context (a Decl or DeclContext), look for a /// code context that is not a closure (a lambda, block, etc.). template <class T> static Decl *getNonClosureContext(T *D) { @@ -967,7 +984,7 @@ bool DeclContext::classof(const Decl *D) { } } -DeclContext::~DeclContext() { } +DeclContext::~DeclContext() = default; /// \brief Find the parent context of this context that will be /// used for unqualified name lookup. @@ -1058,15 +1075,14 @@ static bool isLinkageSpecContext(const DeclContext *DC, } bool DeclContext::isExternCContext() const { - return isLinkageSpecContext(this, clang::LinkageSpecDecl::lang_c); + return isLinkageSpecContext(this, LinkageSpecDecl::lang_c); } const LinkageSpecDecl *DeclContext::getExternCContext() const { const DeclContext *DC = this; while (DC->getDeclKind() != Decl::TranslationUnit) { if (DC->getDeclKind() == Decl::LinkageSpec && - cast<LinkageSpecDecl>(DC)->getLanguage() == - clang::LinkageSpecDecl::lang_c) + cast<LinkageSpecDecl>(DC)->getLanguage() == LinkageSpecDecl::lang_c) return cast<LinkageSpecDecl>(DC); DC = DC->getLexicalParent(); } @@ -1074,7 +1090,7 @@ const LinkageSpecDecl *DeclContext::getExternCContext() const { } bool DeclContext::isExternCXXContext() const { - return isLinkageSpecContext(this, clang::LinkageSpecDecl::lang_cxx); + return isLinkageSpecContext(this, LinkageSpecDecl::lang_cxx); } bool DeclContext::Encloses(const DeclContext *DC) const { @@ -1109,13 +1125,11 @@ DeclContext *DeclContext::getPrimaryContext() { case Decl::ObjCInterface: if (ObjCInterfaceDecl *Def = cast<ObjCInterfaceDecl>(this)->getDefinition()) return Def; - return this; case Decl::ObjCProtocol: if (ObjCProtocolDecl *Def = cast<ObjCProtocolDecl>(this)->getDefinition()) return Def; - return this; case Decl::ObjCCategory: diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 5782b7b56c96..41f2449a9d6a 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -1,4 +1,4 @@ -//===--- DeclCXX.cpp - C++ Declaration AST Node Implementation ------------===// +//===- DeclCXX.cpp - C++ Declaration AST Node Implementation --------------===// // // The LLVM Compiler Infrastructure // @@ -10,26 +10,51 @@ // This file implements the C++ related Decl classes. // //===----------------------------------------------------------------------===// + #include "clang/AST/DeclCXX.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTLambda.h" #include "clang/AST/ASTMutationListener.h" +#include "clang/AST/ASTUnresolvedSet.h" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/LambdaCapture.h" +#include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/ODRHash.h" +#include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" +#include "clang/AST/UnresolvedSet.h" +#include "clang/Basic/Diagnostic.h" #include "clang/Basic/IdentifierTable.h" -#include "llvm/ADT/STLExtras.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> + using namespace clang; //===----------------------------------------------------------------------===// // Decl Allocation/Deallocation Method Implementations //===----------------------------------------------------------------------===// -void AccessSpecDecl::anchor() { } +void AccessSpecDecl::anchor() {} AccessSpecDecl *AccessSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) AccessSpecDecl(EmptyShell()); @@ -76,9 +101,7 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) ImplicitCopyAssignmentHasConstParam(true), HasDeclaredCopyConstructorWithConstParam(false), HasDeclaredCopyAssignmentWithConstParam(false), IsLambda(false), - IsParsingBaseSpecifiers(false), HasODRHash(false), ODRHash(0), - NumBases(0), NumVBases(0), Bases(), VBases(), Definition(D), - FirstFriend() {} + IsParsingBaseSpecifiers(false), HasODRHash(false), Definition(D) {} CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase() const { return Bases.get(Definition->getASTContext().getExternalSource()); @@ -94,13 +117,12 @@ CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C, CXXRecordDecl *PrevDecl) : RecordDecl(K, TK, C, DC, StartLoc, IdLoc, Id, PrevDecl), DefinitionData(PrevDecl ? PrevDecl->DefinitionData - : nullptr), - TemplateOrInstantiation() {} + : nullptr) {} CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, - CXXRecordDecl* PrevDecl, + CXXRecordDecl *PrevDecl, bool DelayTypeCreation) { CXXRecordDecl *R = new (C, DC) CXXRecordDecl(CXXRecord, TK, C, DC, StartLoc, IdLoc, Id, PrevDecl); @@ -148,7 +170,7 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, C.Deallocate(data().getBases()); if (NumBases) { - if (!C.getLangOpts().CPlusPlus1z) { + if (!C.getLangOpts().CPlusPlus17) { // C++ [dcl.init.aggr]p1: // An aggregate is [...] a class with [...] no base classes [...]. data().Aggregate = false; @@ -403,7 +425,6 @@ unsigned CXXRecordDecl::getODRHash() const { 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 @@ -1470,6 +1491,66 @@ bool CXXRecordDecl::isAnyDestructorNoReturn() const { return false; } +static bool isDeclContextInNamespace(const DeclContext *DC) { + while (!DC->isTranslationUnit()) { + if (DC->isNamespace()) + return true; + DC = DC->getParent(); + } + return false; +} + +bool CXXRecordDecl::isInterfaceLike() const { + assert(hasDefinition() && "checking for interface-like without a definition"); + // All __interfaces are inheritently interface-like. + if (isInterface()) + return true; + + // Interface-like types cannot have a user declared constructor, destructor, + // friends, VBases, conversion functions, or fields. Additionally, lambdas + // cannot be interface types. + if (isLambda() || hasUserDeclaredConstructor() || + hasUserDeclaredDestructor() || !field_empty() || hasFriends() || + getNumVBases() > 0 || conversion_end() - conversion_begin() > 0) + return false; + + // No interface-like type can have a method with a definition. + for (const auto *const Method : methods()) + if (Method->isDefined() && !Method->isImplicit()) + return false; + + // Check "Special" types. + const auto *Uuid = getAttr<UuidAttr>(); + // MS SDK declares IUnknown/IDispatch both in the root of a TU, or in an + // extern C++ block directly in the TU. These are only valid if in one + // of these two situations. + if (Uuid && isStruct() && !getDeclContext()->isExternCContext() && + !isDeclContextInNamespace(getDeclContext()) && + ((getName() == "IUnknown" && + Uuid->getGuid() == "00000000-0000-0000-C000-000000000046") || + (getName() == "IDispatch" && + Uuid->getGuid() == "00020400-0000-0000-C000-000000000046"))) { + if (getNumBases() > 0) + return false; + return true; + } + + // FIXME: Any access specifiers is supposed to make this no longer interface + // like. + + // If this isn't a 'special' type, it must have a single interface-like base. + if (getNumBases() != 1) + return false; + + const auto BaseSpec = *bases_begin(); + if (BaseSpec.isVirtual() || BaseSpec.getAccessSpecifier() != AS_public) + return false; + const auto *Base = BaseSpec.getType()->getAsCXXRecordDecl(); + if (Base->isInterface() || !Base->isInterfaceLike()) + return false; + return true; +} + void CXXRecordDecl::completeDefinition() { completeDefinition(nullptr); } @@ -1530,7 +1611,7 @@ bool CXXRecordDecl::mayBeAbstract() const { return false; } -void CXXDeductionGuideDecl::anchor() { } +void CXXDeductionGuideDecl::anchor() {} CXXDeductionGuideDecl *CXXDeductionGuideDecl::Create( ASTContext &C, DeclContext *DC, SourceLocation StartLoc, bool IsExplicit, @@ -1547,7 +1628,7 @@ CXXDeductionGuideDecl *CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C, nullptr, SourceLocation()); } -void CXXMethodDecl::anchor() { } +void CXXMethodDecl::anchor() {} bool CXXMethodDecl::isStatic() const { const CXXMethodDecl *MD = getCanonicalDecl(); @@ -1561,9 +1642,7 @@ bool CXXMethodDecl::isStatic() const { static bool recursivelyOverrides(const CXXMethodDecl *DerivedMD, const CXXMethodDecl *BaseMD) { - for (CXXMethodDecl::method_iterator I = DerivedMD->begin_overridden_methods(), - E = DerivedMD->end_overridden_methods(); I != E; ++I) { - const CXXMethodDecl *MD = *I; + for (const CXXMethodDecl *MD : DerivedMD->overridden_methods()) { if (MD->getCanonicalDecl() == BaseMD->getCanonicalDecl()) return true; if (recursivelyOverrides(MD, BaseMD)) @@ -1728,6 +1807,14 @@ bool CXXMethodDecl::isUsualDeallocationFunction() const { return true; unsigned UsualParams = 1; + // C++ P0722: + // A destroying operator delete is a usual deallocation function if + // removing the std::destroying_delete_t parameter and changing the + // first parameter type from T* to void* results in the signature of + // a usual deallocation function. + if (isDestroyingOperatorDelete()) + ++UsualParams; + // C++ <=14 [basic.stc.dynamic.deallocation]p2: // [...] If class T does not declare such an operator delete but does // declare a member deallocation function named operator delete with @@ -1886,43 +1973,34 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, SourceLocation L, Expr *Init, SourceLocation R, SourceLocation EllipsisLoc) - : Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init), - LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual), - IsWritten(false), SourceOrder(0) -{ -} + : Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init), + LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual), + IsWritten(false), SourceOrder(0) {} CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, FieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R) - : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), - LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), - IsWritten(false), SourceOrder(0) -{ -} + : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), + LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), + IsWritten(false), SourceOrder(0) {} CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, IndirectFieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R) - : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), - LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), - IsWritten(false), SourceOrder(0) -{ -} + : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), + LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), + IsWritten(false), SourceOrder(0) {} CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo, SourceLocation L, Expr *Init, SourceLocation R) - : Initializee(TInfo), MemberOrEllipsisLocation(), Init(Init), - LParenLoc(L), RParenLoc(R), IsDelegating(true), IsVirtual(false), - IsWritten(false), SourceOrder(0) -{ -} + : Initializee(TInfo), Init(Init), LParenLoc(L), RParenLoc(R), + IsDelegating(true), IsVirtual(false), IsWritten(false), SourceOrder(0) {} TypeLoc CXXCtorInitializer::getBaseClassLoc() const { if (isBaseInitializer()) @@ -1962,7 +2040,7 @@ SourceRange CXXCtorInitializer::getSourceRange() const { return SourceRange(getSourceLocation(), getRParenLoc()); } -void CXXConstructorDecl::anchor() { } +void CXXConstructorDecl::anchor() {} CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C, unsigned ID, @@ -2105,7 +2183,7 @@ bool CXXConstructorDecl::isSpecializationCopyingObject() const { return true; } -void CXXDestructorDecl::anchor() { } +void CXXDestructorDecl::anchor() {} CXXDestructorDecl * CXXDestructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) { @@ -2127,16 +2205,17 @@ CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, isInline, isImplicitlyDeclared); } -void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD) { +void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) { auto *First = cast<CXXDestructorDecl>(getFirstDecl()); if (OD && !First->OperatorDelete) { First->OperatorDelete = OD; + First->OperatorDeleteThisArg = ThisArg; if (auto *L = getASTMutationListener()) - L->ResolvedOperatorDelete(First, OD); + L->ResolvedOperatorDelete(First, OD, ThisArg); } } -void CXXConversionDecl::anchor() { } +void CXXConversionDecl::anchor() {} CXXConversionDecl * CXXConversionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { @@ -2166,7 +2245,7 @@ bool CXXConversionDecl::isLambdaToBlockPointerConversion() const { getConversionType()->isBlockPointerType(); } -void LinkageSpecDecl::anchor() { } +void LinkageSpecDecl::anchor() {} LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, DeclContext *DC, @@ -2183,7 +2262,7 @@ LinkageSpecDecl *LinkageSpecDecl::CreateDeserialized(ASTContext &C, SourceLocation(), lang_c, false); } -void UsingDirectiveDecl::anchor() { } +void UsingDirectiveDecl::anchor() {} UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -2217,7 +2296,7 @@ NamespaceDecl::NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, NamespaceDecl *PrevDecl) : NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace), - redeclarable_base(C), LocStart(StartLoc), RBraceLoc(), + redeclarable_base(C), LocStart(StartLoc), AnonOrFirstNamespaceAndInline(nullptr, Inline) { setPreviousDecl(PrevDecl); @@ -2257,21 +2336,25 @@ bool NamespaceDecl::isOriginalNamespace() const { return isFirstDecl(); } NamespaceDecl *NamespaceDecl::getNextRedeclarationImpl() { return getNextRedeclaration(); } + NamespaceDecl *NamespaceDecl::getPreviousDeclImpl() { return getPreviousDecl(); } + NamespaceDecl *NamespaceDecl::getMostRecentDeclImpl() { return getMostRecentDecl(); } -void NamespaceAliasDecl::anchor() { } +void NamespaceAliasDecl::anchor() {} NamespaceAliasDecl *NamespaceAliasDecl::getNextRedeclarationImpl() { return getNextRedeclaration(); } + NamespaceAliasDecl *NamespaceAliasDecl::getPreviousDeclImpl() { return getPreviousDecl(); } + NamespaceAliasDecl *NamespaceAliasDecl::getMostRecentDeclImpl() { return getMostRecentDecl(); } @@ -2298,7 +2381,7 @@ NamespaceAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { SourceLocation(), nullptr); } -void UsingShadowDecl::anchor() { } +void UsingShadowDecl::anchor() {} UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC, SourceLocation Loc, UsingDecl *Using, @@ -2313,7 +2396,7 @@ UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC, UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, EmptyShell Empty) : NamedDecl(K, nullptr, SourceLocation(), DeclarationName()), - redeclarable_base(C), Underlying(), UsingOrNextShadow() {} + redeclarable_base(C) {} UsingShadowDecl * UsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) { @@ -2328,7 +2411,7 @@ UsingDecl *UsingShadowDecl::getUsingDecl() const { return cast<UsingDecl>(Shadow->UsingOrNextShadow); } -void ConstructorUsingShadowDecl::anchor() { } +void ConstructorUsingShadowDecl::anchor() {} ConstructorUsingShadowDecl * ConstructorUsingShadowDecl::Create(ASTContext &C, DeclContext *DC, @@ -2347,7 +2430,7 @@ CXXRecordDecl *ConstructorUsingShadowDecl::getNominatedBaseClass() const { return getUsingDecl()->getQualifier()->getAsRecordDecl(); } -void UsingDecl::anchor() { } +void UsingDecl::anchor() {} void UsingDecl::addShadowDecl(UsingShadowDecl *S) { assert(std::find(shadow_begin(), shadow_end(), S) == shadow_end() && @@ -2399,7 +2482,7 @@ SourceRange UsingDecl::getSourceRange() const { return SourceRange(Begin, getNameInfo().getEndLoc()); } -void UsingPackDecl::anchor() { } +void UsingPackDecl::anchor() {} UsingPackDecl *UsingPackDecl::Create(ASTContext &C, DeclContext *DC, NamedDecl *InstantiatedFrom, @@ -2419,7 +2502,7 @@ UsingPackDecl *UsingPackDecl::CreateDeserialized(ASTContext &C, unsigned ID, return Result; } -void UnresolvedUsingValueDecl::anchor() { } +void UnresolvedUsingValueDecl::anchor() {} UnresolvedUsingValueDecl * UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC, @@ -2447,7 +2530,7 @@ SourceRange UnresolvedUsingValueDecl::getSourceRange() const { return SourceRange(Begin, getNameInfo().getEndLoc()); } -void UnresolvedUsingTypenameDecl::anchor() { } +void UnresolvedUsingTypenameDecl::anchor() {} UnresolvedUsingTypenameDecl * UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC, @@ -2469,7 +2552,7 @@ UnresolvedUsingTypenameDecl::CreateDeserialized(ASTContext &C, unsigned ID) { SourceLocation(), nullptr, SourceLocation()); } -void StaticAssertDecl::anchor() { } +void StaticAssertDecl::anchor() {} StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StaticAssertLoc, diff --git a/lib/AST/DeclFriend.cpp b/lib/AST/DeclFriend.cpp index 121403b07e57..461bf36858b7 100644 --- a/lib/AST/DeclFriend.cpp +++ b/lib/AST/DeclFriend.cpp @@ -1,4 +1,4 @@ -//===--- DeclFriend.cpp - C++ Friend Declaration AST Node Implementation --===// +//===- DeclFriend.cpp - C++ Friend Declaration AST Node Implementation ----===// // // The LLVM Compiler Infrastructure // @@ -12,12 +12,20 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/ASTContext.h" #include "clang/AST/DeclFriend.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" +#include "clang/Basic/LLVM.h" +#include "llvm/Support/Casting.h" +#include <cassert> +#include <cstddef> + using namespace clang; -void FriendDecl::anchor() { } +void FriendDecl::anchor() {} FriendDecl *FriendDecl::getNextFriendSlowCase() { return cast_or_null<FriendDecl>( @@ -28,9 +36,9 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend, SourceLocation FriendL, - ArrayRef<TemplateParameterList*> FriendTypeTPLists) { + ArrayRef<TemplateParameterList *> FriendTypeTPLists) { #ifndef NDEBUG - if (Friend.is<NamedDecl*>()) { + if (Friend.is<NamedDecl *>()) { NamedDecl *D = Friend.get<NamedDecl*>(); assert(isa<FunctionDecl>(D) || isa<CXXRecordDecl>(D) || @@ -42,7 +50,7 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC, assert(D->getFriendObjectKind() || (cast<CXXRecordDecl>(DC)->getTemplateSpecializationKind())); // These template parameters are for friend types only. - assert(FriendTypeTPLists.size() == 0); + assert(FriendTypeTPLists.empty()); } #endif diff --git a/lib/AST/DeclGroup.cpp b/lib/AST/DeclGroup.cpp index 2f95e1f1c345..f74ef9bbb839 100644 --- a/lib/AST/DeclGroup.cpp +++ b/lib/AST/DeclGroup.cpp @@ -1,4 +1,4 @@ -//===--- DeclGroup.cpp - Classes for representing groups of Decls -*- C++ -*-==// +//===- DeclGroup.cpp - Classes for representing groups of Decls -----------===// // // The LLVM Compiler Infrastructure // @@ -13,7 +13,9 @@ #include "clang/AST/DeclGroup.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/Decl.h" +#include <cassert> +#include <memory> + using namespace clang; DeclGroup* DeclGroup::Create(ASTContext &C, Decl **Decls, unsigned NumDecls) { diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index d8bdb6369e94..f95d5def47ac 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -1,4 +1,4 @@ -//===--- DeclObjC.cpp - ObjC Declaration AST Node Implementation ----------===// +//===- DeclObjC.cpp - ObjC Declaration AST Node Implementation ------------===// // // The LLVM Compiler Infrastructure // @@ -15,9 +15,27 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/Attr.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/Stmt.h" -#include "llvm/ADT/STLExtras.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeLoc.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <cstring> +#include <utility> + using namespace clang; //===----------------------------------------------------------------------===// @@ -28,7 +46,6 @@ void ObjCListBase::set(void *const* InList, unsigned Elts, ASTContext &Ctx) { List = nullptr; if (Elts == 0) return; // Setting to an empty list is a noop. - List = new (Ctx) void*[Elts]; NumElts = Elts; memcpy(List, InList, sizeof(void*)*Elts); @@ -48,7 +65,7 @@ void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts, // ObjCInterfaceDecl //===----------------------------------------------------------------------===// -void ObjCContainerDecl::anchor() { } +void ObjCContainerDecl::anchor() {} /// getIvarDecl - This method looks up an ivar in this ContextDecl. /// @@ -82,7 +99,6 @@ ObjCContainerDecl::getMethod(Selector Sel, bool isInstance, // - (int) class_method; // + (float) class_method; // @end - // lookup_result R = lookup(Sel); for (lookup_iterator Meth = R.begin(), MethEnd = R.end(); Meth != MethEnd; ++Meth) { @@ -280,7 +296,7 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration( return nullptr; } -void ObjCInterfaceDecl::anchor() { } +void ObjCInterfaceDecl::anchor() {} ObjCTypeParamList *ObjCInterfaceDecl::getTypeParamList() const { // If this particular declaration has a type parameter list, return it. @@ -341,7 +357,6 @@ SourceLocation ObjCInterfaceDecl::getSuperClassLoc() const { /// FindPropertyVisibleInPrimaryClass - Finds declaration of the property /// with name 'PropertyId' in the primary class; including those in protocols /// (direct or indirect) used by the primary class. -/// ObjCPropertyDecl * ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass( IdentifierInfo *PropertyId, @@ -409,8 +424,7 @@ const ObjCInterfaceDecl *ObjCInterfaceDecl::isObjCRequiresPropertyDefs() const { void ObjCInterfaceDecl::mergeClassExtensionProtocolList( ObjCProtocolDecl *const* ExtList, unsigned ExtNum, - ASTContext &C) -{ + ASTContext &C) { if (data().ExternallyCompleted) LoadExternalDefinition(); @@ -488,7 +502,7 @@ bool ObjCInterfaceDecl::inheritsDesignatedInitializers() const { return true; case DefinitionData::IDI_NotInherited: return false; - case DefinitionData::IDI_Unknown: { + case DefinitionData::IDI_Unknown: // If the class introduced initializers we conservatively assume that we // don't know if any of them is a designated initializer to avoid possible // misleading warnings. @@ -510,7 +524,6 @@ bool ObjCInterfaceDecl::inheritsDesignatedInitializers() const { return data().InheritedDesignatedInitializers == DefinitionData::IDI_Inherited; } - } llvm_unreachable("unexpected InheritedDesignatedInitializers value"); } @@ -902,7 +915,6 @@ ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() { if (ObjCMethodDecl *MD = IFD->getMethod(getSelector(), isInstanceMethod())) return MD; - } else if (ObjCCategoryImplDecl *CImplD = dyn_cast<ObjCCategoryImplDecl>(CtxD)) { if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl()) @@ -1312,7 +1324,8 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const { if (!CheckOverrides) return nullptr; - typedef SmallVector<const ObjCMethodDecl *, 8> OverridesTy; + using OverridesTy = SmallVector<const ObjCMethodDecl *, 8>; + OverridesTy Overrides; getOverriddenMethods(Overrides); for (OverridesTy::const_iterator I = Overrides.begin(), E = Overrides.end(); @@ -1328,7 +1341,7 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const { // ObjCTypeParamDecl //===----------------------------------------------------------------------===// -void ObjCTypeParamDecl::anchor() { } +void ObjCTypeParamDecl::anchor() {} ObjCTypeParamDecl *ObjCTypeParamDecl::Create(ASTContext &ctx, DeclContext *dc, ObjCTypeParamVariance variance, @@ -1373,14 +1386,12 @@ SourceRange ObjCTypeParamDecl::getSourceRange() const { ObjCTypeParamList::ObjCTypeParamList(SourceLocation lAngleLoc, ArrayRef<ObjCTypeParamDecl *> typeParams, SourceLocation rAngleLoc) - : NumParams(typeParams.size()) -{ + : NumParams(typeParams.size()) { Brackets.Begin = lAngleLoc.getRawEncoding(); Brackets.End = rAngleLoc.getRawEncoding(); std::copy(typeParams.begin(), typeParams.end(), begin()); } - ObjCTypeParamList *ObjCTypeParamList::create( ASTContext &ctx, SourceLocation lAngleLoc, @@ -1438,8 +1449,7 @@ ObjCInterfaceDecl::ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, ObjCInterfaceDecl *PrevDecl, bool IsInternal) : ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, AtLoc), - redeclarable_base(C), TypeForDecl(nullptr), TypeParamList(nullptr), - Data() { + redeclarable_base(C) { setPreviousDecl(PrevDecl); // Copy the 'data' pointer over. @@ -1518,19 +1528,22 @@ void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) { } namespace { - struct SynthesizeIvarChunk { - uint64_t Size; - ObjCIvarDecl *Ivar; - SynthesizeIvarChunk(uint64_t size, ObjCIvarDecl *ivar) + +struct SynthesizeIvarChunk { + uint64_t Size; + ObjCIvarDecl *Ivar; + + SynthesizeIvarChunk(uint64_t size, ObjCIvarDecl *ivar) : Size(size), Ivar(ivar) {} - }; +}; - bool operator<(const SynthesizeIvarChunk & LHS, - const SynthesizeIvarChunk &RHS) { - return LHS.Size < RHS.Size; - } +bool operator<(const SynthesizeIvarChunk & LHS, + const SynthesizeIvarChunk &RHS) { + return LHS.Size < RHS.Size; } +} // namespace + /// all_declared_ivar_begin - return first ivar declared in this class, /// its extensions and its implementation. Lazily build the list on first /// access. @@ -1694,7 +1707,7 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto, // ObjCIvarDecl //===----------------------------------------------------------------------===// -void ObjCIvarDecl::anchor() { } +void ObjCIvarDecl::anchor() {} ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC, SourceLocation StartLoc, @@ -1771,7 +1784,7 @@ QualType ObjCIvarDecl::getUsageType(QualType objectType) const { // ObjCAtDefsFieldDecl //===----------------------------------------------------------------------===// -void ObjCAtDefsFieldDecl::anchor() { } +void ObjCAtDefsFieldDecl::anchor() {} ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC, @@ -1791,14 +1804,14 @@ ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::CreateDeserialized(ASTContext &C, // ObjCProtocolDecl //===----------------------------------------------------------------------===// -void ObjCProtocolDecl::anchor() { } +void ObjCProtocolDecl::anchor() {} ObjCProtocolDecl::ObjCProtocolDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, SourceLocation nameLoc, SourceLocation atStartLoc, ObjCProtocolDecl *PrevDecl) : ObjCContainerDecl(ObjCProtocol, DC, Id, nameLoc, atStartLoc), - redeclarable_base(C), Data() { + redeclarable_base(C) { setPreviousDecl(PrevDecl); if (PrevDecl) Data = PrevDecl->Data; @@ -1874,7 +1887,6 @@ void ObjCProtocolDecl::startDefinition() { void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM, PropertyDeclOrder &PO) const { - if (const ObjCProtocolDecl *PDecl = getDefinition()) { for (auto *Prop : PDecl->properties()) { // Insert into PM if not there already. @@ -1921,7 +1933,7 @@ ObjCProtocolDecl::getObjCRuntimeNameAsString() const { // ObjCCategoryDecl //===----------------------------------------------------------------------===// -void ObjCCategoryDecl::anchor() { } +void ObjCCategoryDecl::anchor() {} ObjCCategoryDecl::ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc, SourceLocation ClassNameLoc, @@ -1930,11 +1942,9 @@ ObjCCategoryDecl::ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc, ObjCTypeParamList *typeParamList, SourceLocation IvarLBraceLoc, SourceLocation IvarRBraceLoc) - : ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc), - ClassInterface(IDecl), TypeParamList(nullptr), - NextClassCategory(nullptr), CategoryNameLoc(CategoryNameLoc), - IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) -{ + : ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc), + ClassInterface(IDecl), CategoryNameLoc(CategoryNameLoc), + IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) { setTypeParamList(typeParamList); } @@ -1994,7 +2004,7 @@ void ObjCCategoryDecl::setTypeParamList(ObjCTypeParamList *TPL) { // ObjCCategoryImplDecl //===----------------------------------------------------------------------===// -void ObjCCategoryImplDecl::anchor() { } +void ObjCCategoryImplDecl::anchor() {} ObjCCategoryImplDecl * ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC, @@ -2023,8 +2033,7 @@ ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const { return nullptr; } - -void ObjCImplDecl::anchor() { } +void ObjCImplDecl::anchor() {} void ObjCImplDecl::addPropertyImplementation(ObjCPropertyImplDecl *property) { // FIXME: The context should be correct before we get here. @@ -2052,7 +2061,6 @@ void ObjCImplDecl::setClassInterface(ObjCInterfaceDecl *IFace) { /// FindPropertyImplIvarDecl - This method lookup the ivar in the list of /// properties implemented in this \@implementation block and returns /// the implemented property that uses it. -/// ObjCPropertyImplDecl *ObjCImplDecl:: FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const { for (auto *PID : property_impls()) @@ -2065,7 +2073,6 @@ FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const { /// FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl /// added to the list of those properties \@synthesized/\@dynamic in this /// category \@implementation block. -/// ObjCPropertyImplDecl *ObjCImplDecl:: FindPropertyImplDecl(IdentifierInfo *Id, ObjCPropertyQueryKind QueryKind) const { @@ -2103,7 +2110,7 @@ raw_ostream &clang::operator<<(raw_ostream &OS, // ObjCImplementationDecl //===----------------------------------------------------------------------===// -void ObjCImplementationDecl::anchor() { } +void ObjCImplementationDecl::anchor() {} ObjCImplementationDecl * ObjCImplementationDecl::Create(ASTContext &C, DeclContext *DC, @@ -2155,7 +2162,7 @@ raw_ostream &clang::operator<<(raw_ostream &OS, // ObjCCompatibleAliasDecl //===----------------------------------------------------------------------===// -void ObjCCompatibleAliasDecl::anchor() { } +void ObjCCompatibleAliasDecl::anchor() {} ObjCCompatibleAliasDecl * ObjCCompatibleAliasDecl::Create(ASTContext &C, DeclContext *DC, @@ -2175,7 +2182,7 @@ ObjCCompatibleAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { // ObjCPropertyDecl //===----------------------------------------------------------------------===// -void ObjCPropertyDecl::anchor() { } +void ObjCPropertyDecl::anchor() {} ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 6eeba88e4033..b792c5920a55 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -28,6 +28,7 @@ namespace { class DeclPrinter : public DeclVisitor<DeclPrinter> { raw_ostream &Out; PrintingPolicy Policy; + const ASTContext &Context; unsigned Indentation; bool PrintInstantiation; @@ -36,6 +37,8 @@ namespace { void ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls); void Print(AccessSpecifier AS); + void PrintConstructorInitializers(CXXConstructorDecl *CDecl, + std::string &Proto); /// Print an Objective-C method type in parentheses. /// @@ -48,9 +51,10 @@ namespace { public: DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy, - unsigned Indentation = 0, bool PrintInstantiation = false) - : Out(Out), Policy(Policy), Indentation(Indentation), - PrintInstantiation(PrintInstantiation) { } + const ASTContext &Context, unsigned Indentation = 0, + bool PrintInstantiation = false) + : Out(Out), Policy(Policy), Context(Context), Indentation(Indentation), + PrintInstantiation(PrintInstantiation) {} void VisitDeclContext(DeclContext *DC, bool Indent = true); @@ -115,7 +119,8 @@ void Decl::print(raw_ostream &Out, unsigned Indentation, void Decl::print(raw_ostream &Out, const PrintingPolicy &Policy, unsigned Indentation, bool PrintInstantiation) const { - DeclPrinter Printer(Out, Policy, Indentation, PrintInstantiation); + DeclPrinter Printer(Out, Policy, getASTContext(), Indentation, + PrintInstantiation); Printer.Visit(const_cast<Decl*>(this)); } @@ -192,7 +197,7 @@ LLVM_DUMP_METHOD void DeclContext::dumpDeclContext() const { DC = DC->getParent(); ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext(); - DeclPrinter Printer(llvm::errs(), Ctx.getPrintingPolicy(), 0); + DeclPrinter Printer(llvm::errs(), Ctx.getPrintingPolicy(), Ctx, 0); Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false); } @@ -271,6 +276,71 @@ void DeclPrinter::Print(AccessSpecifier AS) { } } +void DeclPrinter::PrintConstructorInitializers(CXXConstructorDecl *CDecl, + std::string &Proto) { + bool HasInitializerList = false; + for (const auto *BMInitializer : CDecl->inits()) { + if (BMInitializer->isInClassMemberInitializer()) + continue; + + if (!HasInitializerList) { + Proto += " : "; + Out << Proto; + Proto.clear(); + HasInitializerList = true; + } else + Out << ", "; + + if (BMInitializer->isAnyMemberInitializer()) { + FieldDecl *FD = BMInitializer->getAnyMember(); + Out << *FD; + } else { + Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy); + } + + Out << "("; + if (!BMInitializer->getInit()) { + // Nothing to print + } else { + Expr *Init = BMInitializer->getInit(); + if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init)) + Init = Tmp->getSubExpr(); + + Init = Init->IgnoreParens(); + + Expr *SimpleInit = nullptr; + Expr **Args = nullptr; + unsigned NumArgs = 0; + if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { + Args = ParenList->getExprs(); + NumArgs = ParenList->getNumExprs(); + } else if (CXXConstructExpr *Construct = + dyn_cast<CXXConstructExpr>(Init)) { + Args = Construct->getArgs(); + NumArgs = Construct->getNumArgs(); + } else + SimpleInit = Init; + + if (SimpleInit) + SimpleInit->printPretty(Out, nullptr, Policy, Indentation); + else { + for (unsigned I = 0; I != NumArgs; ++I) { + assert(Args[I] != nullptr && "Expected non-null Expr"); + if (isa<CXXDefaultArgExpr>(Args[I])) + break; + + if (I) + Out << ", "; + Args[I]->printPretty(Out, nullptr, Policy, Indentation); + } + } + } + Out << ")"; + if (BMInitializer->isPackExpansion()) + Out << "..."; + } +} + //---------------------------------------------------------------------------- // Common C declarations //---------------------------------------------------------------------------- @@ -467,7 +537,7 @@ void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) { prettyPrintAttributes(D); if (Expr *Init = D->getInitExpr()) { Out << " = "; - Init->printPretty(Out, nullptr, Policy, Indentation); + Init->printPretty(Out, nullptr, Policy, Indentation, &Context); } } @@ -510,18 +580,24 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { PrintingPolicy SubPolicy(Policy); SubPolicy.SuppressSpecifiers = false; std::string Proto; - if (!Policy.SuppressScope) { - if (const NestedNameSpecifier *NS = D->getQualifier()) { - llvm::raw_string_ostream OS(Proto); - NS->print(OS, Policy); + + if (Policy.FullyQualifiedName) { + Proto += D->getQualifiedNameAsString(); + } else { + if (!Policy.SuppressScope) { + if (const NestedNameSpecifier *NS = D->getQualifier()) { + llvm::raw_string_ostream OS(Proto); + NS->print(OS, Policy); + } } + Proto += D->getNameInfo().getAsString(); } - 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); + DeclPrinter TArgPrinter(POut, SubPolicy, Context, Indentation); TArgPrinter.printTemplateArguments(*TArgs); } @@ -539,7 +615,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { Proto += "("; if (FT) { llvm::raw_string_ostream POut(Proto); - DeclPrinter ParamPrinter(POut, SubPolicy, Indentation); + DeclPrinter ParamPrinter(POut, SubPolicy, Context, Indentation); for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { if (i) POut << ", "; ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); @@ -605,67 +681,8 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { } if (CDecl) { - bool HasInitializerList = false; - for (const auto *BMInitializer : CDecl->inits()) { - if (BMInitializer->isInClassMemberInitializer()) - continue; - - if (!HasInitializerList) { - Proto += " : "; - Out << Proto; - Proto.clear(); - HasInitializerList = true; - } else - Out << ", "; - - if (BMInitializer->isAnyMemberInitializer()) { - FieldDecl *FD = BMInitializer->getAnyMember(); - Out << *FD; - } else { - Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy); - } - - Out << "("; - if (!BMInitializer->getInit()) { - // Nothing to print - } else { - Expr *Init = BMInitializer->getInit(); - if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init)) - Init = Tmp->getSubExpr(); - - Init = Init->IgnoreParens(); - - Expr *SimpleInit = nullptr; - Expr **Args = nullptr; - unsigned NumArgs = 0; - if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { - Args = ParenList->getExprs(); - NumArgs = ParenList->getNumExprs(); - } else if (CXXConstructExpr *Construct - = dyn_cast<CXXConstructExpr>(Init)) { - Args = Construct->getArgs(); - NumArgs = Construct->getNumArgs(); - } else - SimpleInit = Init; - - if (SimpleInit) - SimpleInit->printPretty(Out, nullptr, Policy, Indentation); - else { - for (unsigned I = 0; I != NumArgs; ++I) { - assert(Args[I] != nullptr && "Expected non-null Expr"); - if (isa<CXXDefaultArgExpr>(Args[I])) - break; - - if (I) - Out << ", "; - Args[I]->printPretty(Out, nullptr, Policy, Indentation); - } - } - } - Out << ")"; - if (BMInitializer->isPackExpansion()) - Out << "..."; - } + if (!Policy.TerseOutput) + PrintConstructorInitializers(CDecl, Proto); } else if (!ConversionDecl && !isa<CXXDestructorDecl>(D)) { if (FT && FT->hasTrailingReturn()) { if (!GuideDecl) @@ -695,7 +712,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { // This is a K&R function definition, so we need to print the // parameters. Out << '\n'; - DeclPrinter ParamPrinter(Out, SubPolicy, Indentation); + DeclPrinter ParamPrinter(Out, SubPolicy, Context, Indentation); Indentation += Policy.Indentation; for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { Indent(); @@ -709,7 +726,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (D->getBody()) D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation); } else { - if (isa<CXXConstructorDecl>(*D)) + if (!Policy.TerseOutput && isa<CXXConstructorDecl>(*D)) Out << " {}"; } } @@ -1541,7 +1558,19 @@ void DeclPrinter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) { Out << ")"; if (auto *Init = D->getInitializer()) { Out << " initializer("; + switch (D->getInitializerKind()) { + case OMPDeclareReductionDecl::DirectInit: + Out << "omp_priv("; + break; + case OMPDeclareReductionDecl::CopyInit: + Out << "omp_priv = "; + break; + case OMPDeclareReductionDecl::CallInit: + break; + } Init->printPretty(Out, nullptr, Policy, 0); + if (D->getInitializerKind() == OMPDeclareReductionDecl::DirectInit) + Out << ")"; Out << ")"; } } diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 00a6739478bd..a7949b310cef 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -1,4 +1,4 @@ -//===--- DeclTemplate.cpp - Template Declaration AST Node Implementation --===// +//===- DeclTemplate.cpp - Template Declaration AST Node Implementation ----===// // // The LLVM Compiler Infrastructure // @@ -15,13 +15,28 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/TemplateName.h" +#include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" -#include "clang/Basic/IdentifierTable.h" -#include "llvm/ADT/STLExtras.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include <algorithm> +#include <cassert> +#include <cstdint> #include <memory> +#include <utility> + using namespace clang; //===----------------------------------------------------------------------===// @@ -33,9 +48,9 @@ TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc, ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc, Expr *RequiresClause) - : TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc), - NumParams(Params.size()), ContainsUnexpandedParameterPack(false), - HasRequiresClause(static_cast<bool>(RequiresClause)) { + : TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc), + NumParams(Params.size()), ContainsUnexpandedParameterPack(false), + HasRequiresClause(static_cast<bool>(RequiresClause)) { for (unsigned Idx = 0; Idx < NumParams; ++Idx) { NamedDecl *P = Params[Idx]; begin()[Idx] = P; @@ -124,10 +139,12 @@ static void AdoptTemplateParameterList(TemplateParameterList *Params, } namespace clang { + void *allocateDefaultArgStorageChain(const ASTContext &C) { return new (C) char[sizeof(void*) * 2]; } -} + +} // namespace clang //===----------------------------------------------------------------------===// // RedeclarableTemplateDecl Implementation @@ -165,14 +182,28 @@ RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() c return Common; } +void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const { + // Grab the most recent declaration to ensure we've loaded any lazy + // redeclarations of this template. + CommonBase *CommonBasePtr = getMostRecentDecl()->getCommonPtr(); + if (CommonBasePtr->LazySpecializations) { + ASTContext &Context = getASTContext(); + uint32_t *Specs = CommonBasePtr->LazySpecializations; + CommonBasePtr->LazySpecializations = nullptr; + for (uint32_t I = 0, N = *Specs++; I != N; ++I) + (void)Context.getExternalSource()->GetExternalDecl(Specs[I]); + } +} + template<class EntryType> typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType * RedeclarableTemplateDecl::findSpecializationImpl( llvm::FoldingSetVector<EntryType> &Specs, ArrayRef<TemplateArgument> Args, void *&InsertPos) { - typedef SpecEntryTraits<EntryType> SETraits; + using SETraits = SpecEntryTraits<EntryType>; + llvm::FoldingSetNodeID ID; - EntryType::Profile(ID,Args, getASTContext()); + EntryType::Profile(ID, Args, getASTContext()); EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos); return Entry ? SETraits::getDecl(Entry)->getMostRecentDecl() : nullptr; } @@ -181,7 +212,8 @@ template<class Derived, class EntryType> void RedeclarableTemplateDecl::addSpecializationImpl( llvm::FoldingSetVector<EntryType> &Specializations, EntryType *Entry, void *InsertPos) { - typedef SpecEntryTraits<EntryType> SETraits; + using SETraits = SpecEntryTraits<EntryType>; + if (InsertPos) { #ifndef NDEBUG void *CorrectInsertPos; @@ -232,18 +264,7 @@ FunctionTemplateDecl::newCommon(ASTContext &C) const { } void FunctionTemplateDecl::LoadLazySpecializations() const { - // Grab the most recent declaration to ensure we've loaded any lazy - // redeclarations of this template. - // - // FIXME: Avoid walking the entire redeclaration chain here. - Common *CommonPtr = getMostRecentDecl()->getCommonPtr(); - if (CommonPtr->LazySpecializations) { - ASTContext &Context = getASTContext(); - uint32_t *Specs = CommonPtr->LazySpecializations; - CommonPtr->LazySpecializations = nullptr; - for (uint32_t I = 0, N = *Specs++; I != N; ++I) - (void)Context.getExternalSource()->GetExternalDecl(Specs[I]); - } + loadLazySpecializationsImpl(); } llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> & @@ -311,18 +332,7 @@ ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C, } void ClassTemplateDecl::LoadLazySpecializations() const { - // Grab the most recent declaration to ensure we've loaded any lazy - // redeclarations of this template. - // - // FIXME: Avoid walking the entire redeclaration chain here. - Common *CommonPtr = getMostRecentDecl()->getCommonPtr(); - if (CommonPtr->LazySpecializations) { - ASTContext &Context = getASTContext(); - uint32_t *Specs = CommonPtr->LazySpecializations; - CommonPtr->LazySpecializations = nullptr; - for (uint32_t I = 0, N = *Specs++; I != N; ++I) - (void)Context.getExternalSource()->GetExternalDecl(Specs[I]); - } + loadLazySpecializationsImpl(); } llvm::FoldingSetVector<ClassTemplateSpecializationDecl> & @@ -562,7 +572,7 @@ SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const { // TemplateTemplateParmDecl Method Implementations //===----------------------------------------------------------------------===// -void TemplateTemplateParmDecl::anchor() { } +void TemplateTemplateParmDecl::anchor() {} TemplateTemplateParmDecl::TemplateTemplateParmDecl( DeclContext *DC, SourceLocation L, unsigned D, unsigned P, @@ -665,11 +675,12 @@ FunctionTemplateSpecializationInfo::Create(ASTContext &C, FunctionDecl *FD, // TemplateDecl Implementation //===----------------------------------------------------------------------===// -void TemplateDecl::anchor() { } +void TemplateDecl::anchor() {} //===----------------------------------------------------------------------===// // ClassTemplateSpecializationDecl Implementation //===----------------------------------------------------------------------===// + ClassTemplateSpecializationDecl:: ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, DeclContext *DC, SourceLocation StartLoc, @@ -677,11 +688,9 @@ ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args, ClassTemplateSpecializationDecl *PrevDecl) - : CXXRecordDecl(DK, TK, Context, DC, StartLoc, IdLoc, - SpecializedTemplate->getIdentifier(), - PrevDecl), + : CXXRecordDecl(DK, TK, Context, DC, StartLoc, IdLoc, + SpecializedTemplate->getIdentifier(), PrevDecl), SpecializedTemplate(SpecializedTemplate), - ExplicitInfo(nullptr), TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)), SpecializationKind(TSK_Undeclared) { } @@ -690,7 +699,7 @@ ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C, Kind DK) : CXXRecordDecl(DK, TTK_Struct, C, nullptr, SourceLocation(), SourceLocation(), nullptr, nullptr), - ExplicitInfo(nullptr), SpecializationKind(TSK_Undeclared) {} + SpecializationKind(TSK_Undeclared) {} ClassTemplateSpecializationDecl * ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK, @@ -726,12 +735,10 @@ void ClassTemplateSpecializationDecl::getNameForDiagnostic( auto *PS = dyn_cast<ClassTemplatePartialSpecializationDecl>(this); if (const ASTTemplateArgumentListInfo *ArgsAsWritten = PS ? PS->getTemplateArgsAsWritten() : nullptr) { - TemplateSpecializationType::PrintTemplateArgumentList( - OS, ArgsAsWritten->arguments(), Policy); + printTemplateArgumentList(OS, ArgsAsWritten->arguments(), Policy); } else { const TemplateArgumentList &TemplateArgs = getTemplateArgs(); - TemplateSpecializationType::PrintTemplateArgumentList( - OS, TemplateArgs.asArray(), Policy); + printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy); } } @@ -762,7 +769,7 @@ ClassTemplateSpecializationDecl::getSourceRange() const { // An implicit instantiation of a class template partial specialization // uses ExplicitInfo to record the TypeAsWritten, but the source // locations should be retrieved from the instantiation pattern. - typedef ClassTemplatePartialSpecializationDecl CTPSDecl; + using CTPSDecl = ClassTemplatePartialSpecializationDecl; CTPSDecl *ctpsd = const_cast<CTPSDecl*>(cast<CTPSDecl>(this)); CTPSDecl *inst_from = ctpsd->getInstantiatedFromMember(); assert(inst_from != nullptr); @@ -785,7 +792,7 @@ ClassTemplateSpecializationDecl::getSourceRange() const { //===----------------------------------------------------------------------===// // ClassTemplatePartialSpecializationDecl Implementation //===----------------------------------------------------------------------===// -void ClassTemplatePartialSpecializationDecl::anchor() { } +void ClassTemplatePartialSpecializationDecl::anchor() {} ClassTemplatePartialSpecializationDecl:: ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK, @@ -797,14 +804,12 @@ ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK, ArrayRef<TemplateArgument> Args, const ASTTemplateArgumentListInfo *ArgInfos, ClassTemplatePartialSpecializationDecl *PrevDecl) - : ClassTemplateSpecializationDecl(Context, - ClassTemplatePartialSpecialization, - TK, DC, StartLoc, IdLoc, - SpecializedTemplate, - Args, PrevDecl), - TemplateParams(Params), ArgsAsWritten(ArgInfos), - InstantiatedFromMember(nullptr, false) -{ + : ClassTemplateSpecializationDecl(Context, + ClassTemplatePartialSpecialization, + TK, DC, StartLoc, IdLoc, + SpecializedTemplate, Args, PrevDecl), + TemplateParams(Params), ArgsAsWritten(ArgInfos), + InstantiatedFromMember(nullptr, false) { AdoptTemplateParameterList(Params, this); } @@ -845,7 +850,7 @@ ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C, // FriendTemplateDecl Implementation //===----------------------------------------------------------------------===// -void FriendTemplateDecl::anchor() { } +void FriendTemplateDecl::anchor() {} FriendTemplateDecl * FriendTemplateDecl::Create(ASTContext &Context, DeclContext *DC, @@ -891,7 +896,7 @@ TypeAliasTemplateDecl::newCommon(ASTContext &C) const { // ClassScopeFunctionSpecializationDecl Implementation //===----------------------------------------------------------------------===// -void ClassScopeFunctionSpecializationDecl::anchor() { } +void ClassScopeFunctionSpecializationDecl::anchor() {} ClassScopeFunctionSpecializationDecl * ClassScopeFunctionSpecializationDecl::CreateDeserialized(ASTContext &C, @@ -927,21 +932,8 @@ VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C, DeclarationName(), nullptr, nullptr); } -// TODO: Unify across class, function and variable templates? -// May require moving this and Common to RedeclarableTemplateDecl. void VarTemplateDecl::LoadLazySpecializations() const { - // Grab the most recent declaration to ensure we've loaded any lazy - // redeclarations of this template. - // - // FIXME: Avoid walking the entire redeclaration chain here. - Common *CommonPtr = getMostRecentDecl()->getCommonPtr(); - if (CommonPtr->LazySpecializations) { - ASTContext &Context = getASTContext(); - uint32_t *Specs = CommonPtr->LazySpecializations; - CommonPtr->LazySpecializations = nullptr; - for (uint32_t I = 0, N = *Specs++; I != N; ++I) - (void)Context.getExternalSource()->GetExternalDecl(Specs[I]); - } + loadLazySpecializationsImpl(); } llvm::FoldingSetVector<VarTemplateSpecializationDecl> & @@ -1020,21 +1012,22 @@ VarTemplateDecl::findPartialSpecInstantiatedFromMember( //===----------------------------------------------------------------------===// // VarTemplateSpecializationDecl Implementation //===----------------------------------------------------------------------===// + VarTemplateSpecializationDecl::VarTemplateSpecializationDecl( Kind DK, ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, StorageClass S, ArrayRef<TemplateArgument> Args) : VarDecl(DK, Context, DC, StartLoc, IdLoc, SpecializedTemplate->getIdentifier(), T, TInfo, S), - SpecializedTemplate(SpecializedTemplate), ExplicitInfo(nullptr), + SpecializedTemplate(SpecializedTemplate), TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)), - SpecializationKind(TSK_Undeclared) {} + SpecializationKind(TSK_Undeclared), IsCompleteDefinition(false) {} VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(Kind DK, ASTContext &C) : VarDecl(DK, C, nullptr, SourceLocation(), SourceLocation(), nullptr, QualType(), nullptr, SC_None), - ExplicitInfo(nullptr), SpecializationKind(TSK_Undeclared) {} + SpecializationKind(TSK_Undeclared), IsCompleteDefinition(false) {} VarTemplateSpecializationDecl *VarTemplateSpecializationDecl::Create( ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, @@ -1058,12 +1051,10 @@ void VarTemplateSpecializationDecl::getNameForDiagnostic( auto *PS = dyn_cast<VarTemplatePartialSpecializationDecl>(this); if (const ASTTemplateArgumentListInfo *ArgsAsWritten = PS ? PS->getTemplateArgsAsWritten() : nullptr) { - TemplateSpecializationType::PrintTemplateArgumentList( - OS, ArgsAsWritten->arguments(), Policy); + printTemplateArgumentList(OS, ArgsAsWritten->arguments(), Policy); } else { const TemplateArgumentList &TemplateArgs = getTemplateArgs(); - TemplateSpecializationType::PrintTemplateArgumentList( - OS, TemplateArgs.asArray(), Policy); + printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy); } } @@ -1085,6 +1076,7 @@ void VarTemplateSpecializationDecl::setTemplateArgsInfo( //===----------------------------------------------------------------------===// // VarTemplatePartialSpecializationDecl Implementation //===----------------------------------------------------------------------===// + void VarTemplatePartialSpecializationDecl::anchor() {} VarTemplatePartialSpecializationDecl::VarTemplatePartialSpecializationDecl( diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp index 1f8e26deda97..31bae93c3cb5 100644 --- a/lib/AST/DeclarationName.cpp +++ b/lib/AST/DeclarationName.cpp @@ -1,4 +1,4 @@ -//===-- DeclarationName.cpp - Declaration names implementation --*- C++ -*-===// +//===- DeclarationName.cpp - Declaration names implementation -------------===// // // The LLVM Compiler Infrastructure // @@ -11,20 +11,36 @@ // classes. // //===----------------------------------------------------------------------===// + #include "clang/AST/DeclarationName.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/PrettyPrinter.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeOrdering.h" #include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/SourceLocation.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <string> + using namespace clang; namespace clang { + /// CXXSpecialName - Records the type associated with one of the /// "special" kinds of declaration names in C++, e.g., constructors, /// destructors, and conversion functions. @@ -89,6 +105,8 @@ public: } }; +} // namespace clang + static int compareInt(unsigned A, unsigned B) { return (A < B ? -1 : (A > B ? 1 : 0)); } @@ -197,10 +215,9 @@ void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) { case DeclarationName::CXXConstructorName: return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy); - case DeclarationName::CXXDestructorName: { + case DeclarationName::CXXDestructorName: OS << '~'; return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy); - } case DeclarationName::CXXDeductionGuideName: OS << "<deduction guide for "; @@ -250,13 +267,15 @@ void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) { llvm_unreachable("Unexpected declaration name kind"); } +namespace clang { + raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) { LangOptions LO; N.print(OS, PrintingPolicy(LO)); return OS; } -} // end namespace clang +} // namespace clang DeclarationName::NameKind DeclarationName::getNameKind() const { switch (getStoredNameKind()) { diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index afc7fa8ea094..55061aa462e5 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1695,6 +1695,26 @@ CXXBaseSpecifier **CastExpr::path_buffer() { } } +const FieldDecl *CastExpr::getTargetFieldForToUnionCast(QualType unionType, + QualType opType) { + auto RD = unionType->castAs<RecordType>()->getDecl(); + return getTargetFieldForToUnionCast(RD, opType); +} + +const FieldDecl *CastExpr::getTargetFieldForToUnionCast(const RecordDecl *RD, + QualType OpType) { + auto &Ctx = RD->getASTContext(); + RecordDecl::field_iterator Field, FieldEnd; + for (Field = RD->field_begin(), FieldEnd = RD->field_end(); + Field != FieldEnd; ++Field) { + if (Ctx.hasSameUnqualifiedType(Field->getType(), OpType) && + !Field->isUnnamedBitfield()) { + return *Field; + } + } + return nullptr; +} + ImplicitCastExpr *ImplicitCastExpr::Create(const ASTContext &C, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, @@ -1760,6 +1780,7 @@ BinaryOperator::getOverloadedOpcode(OverloadedOperatorKind OO) { case OO_Amp: return BO_And; case OO_Pipe: return BO_Or; case OO_Equal: return BO_Assign; + case OO_Spaceship: return BO_Cmp; case OO_Less: return BO_LT; case OO_Greater: return BO_GT; case OO_PlusEqual: return BO_AddAssign; @@ -1791,6 +1812,7 @@ OverloadedOperatorKind BinaryOperator::getOverloadedOperator(Opcode Opc) { OO_Star, OO_Slash, OO_Percent, OO_Plus, OO_Minus, OO_LessLess, OO_GreaterGreater, + OO_Spaceship, OO_Less, OO_Greater, OO_LessEqual, OO_GreaterEqual, OO_EqualEqual, OO_ExclaimEqual, OO_Amp, @@ -1809,6 +1831,38 @@ OverloadedOperatorKind BinaryOperator::getOverloadedOperator(Opcode Opc) { return OverOps[Opc]; } +bool BinaryOperator::isNullPointerArithmeticExtension(ASTContext &Ctx, + Opcode Opc, + Expr *LHS, Expr *RHS) { + if (Opc != BO_Add) + return false; + + // Check that we have one pointer and one integer operand. + Expr *PExp; + if (LHS->getType()->isPointerType()) { + if (!RHS->getType()->isIntegerType()) + return false; + PExp = LHS; + } else if (RHS->getType()->isPointerType()) { + if (!LHS->getType()->isIntegerType()) + return false; + PExp = RHS; + } else { + return false; + } + + // Check that the pointer is a nullptr. + if (!PExp->IgnoreParenCasts() + ->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull)) + return false; + + // Check that the pointee type is char-sized. + const PointerType *PTy = PExp->getType()->getAs<PointerType>(); + if (!PTy || !PTy->getPointeeType()->isCharType()) + return false; + + return true; +} InitListExpr::InitListExpr(const ASTContext &C, SourceLocation lbraceloc, ArrayRef<Expr*> initExprs, SourceLocation rbraceloc) : Expr(InitListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false, @@ -1899,6 +1953,17 @@ bool InitListExpr::isTransparent() const { getInit(0)->getType().getCanonicalType(); } +bool InitListExpr::isIdiomaticZeroInitializer(const LangOptions &LangOpts) const { + assert(isSyntacticForm() && "only test syntactic form as zero initializer"); + + if (LangOpts.CPlusPlus || getNumInits() != 1) { + return false; + } + + const IntegerLiteral *Lit = dyn_cast<IntegerLiteral>(getInit(0)); + return Lit && Lit->getValue() == 0; +} + SourceLocation InitListExpr::getLocStart() const { if (InitListExpr *SyntacticForm = getSyntacticForm()) return SyntacticForm->getLocStart(); @@ -2235,7 +2300,8 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr()->IgnoreParens()); if (!(DRE && isa<VarDecl>(DRE->getDecl()) && - cast<VarDecl>(DRE->getDecl())->hasLocalStorage())) { + cast<VarDecl>(DRE->getDecl())->hasLocalStorage()) && + !isa<CallExpr>(CE->getSubExpr()->IgnoreParens())) { return CE->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); } @@ -3230,20 +3296,20 @@ Expr::isNullPointerConstant(ASTContext &Ctx, // Check that it is a cast to void*. if (const PointerType *PT = CE->getType()->getAs<PointerType>()) { QualType Pointee = PT->getPointeeType(); - Qualifiers Q = Pointee.getQualifiers(); - // In OpenCL v2.0 generic address space acts as a placeholder - // and should be ignored. - bool IsASValid = true; - if (Ctx.getLangOpts().OpenCLVersion >= 200) { - if (Pointee.getAddressSpace() == LangAS::opencl_generic) - Q.removeAddressSpace(); - else - IsASValid = false; - } - - if (IsASValid && !Q.hasQualifiers() && - Pointee->isVoidType() && // to void* - CE->getSubExpr()->getType()->isIntegerType()) // from int. + // Only (void*)0 or equivalent are treated as nullptr. If pointee type + // has non-default address space it is not treated as nullptr. + // (__generic void*)0 in OpenCL 2.0 should not be treated as nullptr + // since it cannot be assigned to a pointer to constant address space. + bool PointeeHasDefaultAS = + Pointee.getAddressSpace() == LangAS::Default || + (Ctx.getLangOpts().OpenCLVersion >= 200 && + Pointee.getAddressSpace() == LangAS::opencl_generic) || + (Ctx.getLangOpts().OpenCL && + Ctx.getLangOpts().OpenCLVersion < 200 && + Pointee.getAddressSpace() == LangAS::opencl_private); + + if (PointeeHasDefaultAS && Pointee->isVoidType() && // to void* + CE->getSubExpr()->getType()->isIntegerType()) // from int. return CE->getSubExpr()->isNullPointerConstant(Ctx, NPC); } } @@ -3938,10 +4004,12 @@ AtomicExpr::AtomicExpr(SourceLocation BLoc, ArrayRef<Expr*> args, unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) { switch (Op) { case AO__c11_atomic_init: + case AO__opencl_atomic_init: case AO__c11_atomic_load: case AO__atomic_load_n: return 2; + case AO__opencl_atomic_load: case AO__c11_atomic_store: case AO__c11_atomic_exchange: case AO__atomic_load: @@ -3967,6 +4035,15 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) { case AO__atomic_nand_fetch: return 3; + case AO__opencl_atomic_store: + case AO__opencl_atomic_exchange: + case AO__opencl_atomic_fetch_add: + case AO__opencl_atomic_fetch_sub: + case AO__opencl_atomic_fetch_and: + case AO__opencl_atomic_fetch_or: + case AO__opencl_atomic_fetch_xor: + case AO__opencl_atomic_fetch_min: + case AO__opencl_atomic_fetch_max: case AO__atomic_exchange: return 4; @@ -3974,6 +4051,8 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) { case AO__c11_atomic_compare_exchange_weak: return 5; + case AO__opencl_atomic_compare_exchange_strong: + case AO__opencl_atomic_compare_exchange_weak: case AO__atomic_compare_exchange: case AO__atomic_compare_exchange_n: return 6; @@ -3981,6 +4060,13 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) { llvm_unreachable("unknown atomic op"); } +QualType AtomicExpr::getValueType() const { + auto T = getPtr()->getType()->castAs<PointerType>()->getPointeeType(); + if (auto AT = T->getAs<AtomicType>()) + return AT->getValueType(); + return T; +} + QualType OMPArraySectionExpr::getBaseOriginalType(const Expr *Base) { unsigned ArraySectionCount = 0; while (auto *OASE = dyn_cast<OMPArraySectionExpr>(Base->IgnoreParens())) { diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index fe45b5e47f36..262a1e3ff9d5 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -1,4 +1,4 @@ -//===--- ExprCXX.cpp - (C++) Expression AST Node Implementation -----------===// +//===- ExprCXX.cpp - (C++) Expression AST Node Implementation -------------===// // // The LLVM Compiler Infrastructure // @@ -11,15 +11,33 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/ExprCXX.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclAccessPair.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/ExprCXX.h" +#include "clang/AST/DeclarationName.h" +#include "clang/AST/Expr.h" +#include "clang/AST/LambdaCapture.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" -#include "clang/Basic/IdentifierTable.h" -using namespace clang; +#include "clang/Basic/LLVM.h" +#include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include <cassert> +#include <cstddef> +#include <cstring> +#include <memory> +using namespace clang; //===----------------------------------------------------------------------===// // Child Iterators for iterating over subexpressions/substatements @@ -85,15 +103,14 @@ CXXNewExpr::CXXNewExpr(const ASTContext &C, bool globalNew, Expr *initializer, QualType ty, TypeSourceInfo *allocatedTypeInfo, SourceRange Range, SourceRange directInitRange) - : Expr(CXXNewExprClass, ty, VK_RValue, OK_Ordinary, - ty->isDependentType(), ty->isDependentType(), - ty->isInstantiationDependentType(), - ty->containsUnexpandedParameterPack()), - SubExprs(nullptr), OperatorNew(operatorNew), OperatorDelete(operatorDelete), - AllocatedTypeInfo(allocatedTypeInfo), TypeIdParens(typeIdParens), - Range(Range), DirectInitRange(directInitRange), - GlobalNew(globalNew), PassAlignment(PassAlignment), - UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) { + : Expr(CXXNewExprClass, ty, VK_RValue, OK_Ordinary, ty->isDependentType(), + ty->isDependentType(), ty->isInstantiationDependentType(), + ty->containsUnexpandedParameterPack()), + OperatorNew(operatorNew), OperatorDelete(operatorDelete), + AllocatedTypeInfo(allocatedTypeInfo), TypeIdParens(typeIdParens), + Range(Range), DirectInitRange(directInitRange), GlobalNew(globalNew), + PassAlignment(PassAlignment), + UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) { assert((initializer != nullptr || initializationStyle == NoInit) && "Only NoInit can have no initializer."); StoredInitializationStyle = initializer ? initializationStyle + 1 : 0; @@ -160,6 +177,22 @@ bool CXXNewExpr::shouldNullCheckAllocation(const ASTContext &Ctx) const { // CXXDeleteExpr QualType CXXDeleteExpr::getDestroyedType() const { const Expr *Arg = getArgument(); + + // For a destroying operator delete, we may have implicitly converted the + // pointer type to the type of the parameter of the 'operator delete' + // function. + while (auto *ICE = dyn_cast<ImplicitCastExpr>(Arg)) { + if (ICE->getCastKind() == CK_DerivedToBase || + ICE->getCastKind() == CK_UncheckedDerivedToBase || + ICE->getCastKind() == CK_NoOp) { + assert((ICE->getCastKind() == CK_NoOp || + getOperatorDelete()->isDestroyingOperatorDelete()) && + "only a destroying operator delete can have a converted arg"); + Arg = ICE->getSubExpr(); + } else + break; + } + // The type-to-delete may not be a pointer if it's a dependent type. const QualType ArgType = Arg->getType(); @@ -171,8 +204,7 @@ QualType CXXDeleteExpr::getDestroyedType() const { // CXXPseudoDestructorExpr PseudoDestructorTypeStorage::PseudoDestructorTypeStorage(TypeSourceInfo *Info) - : Type(Info) -{ + : Type(Info) { Location = Info->getTypeLoc().getLocalSourceRange().getBegin(); } @@ -209,7 +241,7 @@ CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(const ASTContext &Context, Base(static_cast<Stmt *>(Base)), IsArrow(isArrow), OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc), ScopeType(ScopeType), ColonColonLoc(ColonColonLoc), TildeLoc(TildeLoc), - DestroyedType(DestroyedType) { } + DestroyedType(DestroyedType) {} QualType CXXPseudoDestructorExpr::getDestroyedType() const { if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo()) @@ -235,8 +267,7 @@ UnresolvedLookupExpr::Create(const ASTContext &C, bool ADL, const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin, - UnresolvedSetIterator End) -{ + UnresolvedSetIterator End) { assert(Args || TemplateKWLoc.isValid()); unsigned num_args = Args ? Args->size() : 0; @@ -274,21 +305,20 @@ OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C, bool KnownDependent, bool KnownInstantiationDependent, bool KnownContainsUnexpandedParameterPack) - : Expr(K, C.OverloadTy, VK_LValue, OK_Ordinary, KnownDependent, - KnownDependent, - (KnownInstantiationDependent || - NameInfo.isInstantiationDependent() || - (QualifierLoc && - QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())), - (KnownContainsUnexpandedParameterPack || - NameInfo.containsUnexpandedParameterPack() || - (QualifierLoc && - QualifierLoc.getNestedNameSpecifier() - ->containsUnexpandedParameterPack()))), - NameInfo(NameInfo), QualifierLoc(QualifierLoc), - Results(nullptr), NumResults(End - Begin), - HasTemplateKWAndArgsInfo(TemplateArgs != nullptr || - TemplateKWLoc.isValid()) { + : Expr(K, C.OverloadTy, VK_LValue, OK_Ordinary, KnownDependent, + KnownDependent, + (KnownInstantiationDependent || + NameInfo.isInstantiationDependent() || + (QualifierLoc && + QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())), + (KnownContainsUnexpandedParameterPack || + NameInfo.containsUnexpandedParameterPack() || + (QualifierLoc && + QualifierLoc.getNestedNameSpecifier() + ->containsUnexpandedParameterPack()))), + NameInfo(NameInfo), QualifierLoc(QualifierLoc), NumResults(End - Begin), + HasTemplateKWAndArgsInfo(TemplateArgs != nullptr || + TemplateKWLoc.isValid()) { NumResults = End - Begin; if (NumResults) { // Determine whether this expression is type-dependent. @@ -493,7 +523,6 @@ CXXMethodDecl *CXXMemberCallExpr::getMethodDecl() const { return nullptr; } - CXXRecordDecl *CXXMemberCallExpr::getRecordDecl() const { Expr* ThisArg = getImplicitObjectArgument(); if (!ThisArg) @@ -505,7 +534,6 @@ CXXRecordDecl *CXXMemberCallExpr::getRecordDecl() const { return ThisArg->getType()->getAsCXXRecordDecl(); } - //===----------------------------------------------------------------------===// // Named casts //===----------------------------------------------------------------------===// @@ -742,16 +770,12 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(const ASTContext &C, bool ListInitialization, bool StdInitListInitialization, bool ZeroInitialization) - : CXXConstructExpr(C, CXXTemporaryObjectExprClass, Type, - TSI->getTypeLoc().getBeginLoc(), - Cons, false, Args, - HadMultipleCandidates, - ListInitialization, - StdInitListInitialization, - ZeroInitialization, - CXXConstructExpr::CK_Complete, ParenOrBraceRange), - Type(TSI) { -} + : CXXConstructExpr(C, CXXTemporaryObjectExprClass, Type, + TSI->getTypeLoc().getBeginLoc(), Cons, false, Args, + HadMultipleCandidates, ListInitialization, + StdInitListInitialization, ZeroInitialization, + CXXConstructExpr::CK_Complete, ParenOrBraceRange), + Type(TSI) {} SourceLocation CXXTemporaryObjectExpr::getLocStart() const { return Type->getTypeLoc().getBeginLoc(); @@ -794,18 +818,16 @@ CXXConstructExpr::CXXConstructExpr(const ASTContext &C, StmtClass SC, bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenOrBraceRange) - : Expr(SC, T, VK_RValue, OK_Ordinary, - T->isDependentType(), T->isDependentType(), - T->isInstantiationDependentType(), - T->containsUnexpandedParameterPack()), - Constructor(Ctor), Loc(Loc), ParenOrBraceRange(ParenOrBraceRange), - NumArgs(Args.size()), - Elidable(Elidable), HadMultipleCandidates(HadMultipleCandidates), - ListInitialization(ListInitialization), - StdInitListInitialization(StdInitListInitialization), - ZeroInitialization(ZeroInitialization), - ConstructKind(ConstructKind), Args(nullptr) -{ + : Expr(SC, T, VK_RValue, OK_Ordinary, + T->isDependentType(), T->isDependentType(), + T->isInstantiationDependentType(), + T->containsUnexpandedParameterPack()), + Constructor(Ctor), Loc(Loc), ParenOrBraceRange(ParenOrBraceRange), + NumArgs(Args.size()), Elidable(Elidable), + HadMultipleCandidates(HadMultipleCandidates), + ListInitialization(ListInitialization), + StdInitListInitialization(StdInitListInitialization), + ZeroInitialization(ZeroInitialization), ConstructKind(ConstructKind) { if (NumArgs) { this->Args = new (C) Stmt*[Args.size()]; @@ -827,8 +849,7 @@ CXXConstructExpr::CXXConstructExpr(const ASTContext &C, StmtClass SC, LambdaCapture::LambdaCapture(SourceLocation Loc, bool Implicit, LambdaCaptureKind Kind, VarDecl *Var, SourceLocation EllipsisLoc) - : DeclAndBits(Var, 0), Loc(Loc), EllipsisLoc(EllipsisLoc) -{ + : DeclAndBits(Var, 0), Loc(Loc), EllipsisLoc(EllipsisLoc) { unsigned Bits = 0; if (Implicit) Bits |= Capture_Implicit; @@ -995,7 +1016,7 @@ CompoundStmt *LambdaExpr::getBody() const { // initialized in ASTStmtReader::VisitLambdaExpr, but for reasons I // don't understand, that doesn't work. if (!getStoredStmts()[NumCaptures]) - *const_cast<clang::Stmt **>(&getStoredStmts()[NumCaptures]) = + *const_cast<Stmt **>(&getStoredStmts()[NumCaptures]) = getCallOperator()->getBody(); return static_cast<CompoundStmt *>(getStoredStmts()[NumCaptures]); @@ -1008,12 +1029,12 @@ bool LambdaExpr::isMutable() const { ExprWithCleanups::ExprWithCleanups(Expr *subexpr, bool CleanupsHaveSideEffects, ArrayRef<CleanupObject> objects) - : Expr(ExprWithCleanupsClass, subexpr->getType(), - subexpr->getValueKind(), subexpr->getObjectKind(), - subexpr->isTypeDependent(), subexpr->isValueDependent(), - subexpr->isInstantiationDependent(), - subexpr->containsUnexpandedParameterPack()), - SubExpr(subexpr) { + : Expr(ExprWithCleanupsClass, subexpr->getType(), + subexpr->getValueKind(), subexpr->getObjectKind(), + subexpr->isTypeDependent(), subexpr->isValueDependent(), + subexpr->isInstantiationDependent(), + subexpr->containsUnexpandedParameterPack()), + SubExpr(subexpr) { ExprWithCleanupsBits.CleanupsHaveSideEffects = CleanupsHaveSideEffects; ExprWithCleanupsBits.NumObjects = objects.size(); for (unsigned i = 0, e = objects.size(); i != e; ++i) @@ -1030,7 +1051,7 @@ ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, Expr *subexpr, } ExprWithCleanups::ExprWithCleanups(EmptyShell empty, unsigned numObjects) - : Expr(ExprWithCleanupsClass, empty) { + : Expr(ExprWithCleanupsClass, empty) { ExprWithCleanupsBits.NumObjects = numObjects; } @@ -1046,20 +1067,18 @@ CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type, SourceLocation LParenLoc, ArrayRef<Expr*> Args, SourceLocation RParenLoc) - : Expr(CXXUnresolvedConstructExprClass, - Type->getType().getNonReferenceType(), - (Type->getType()->isLValueReferenceType() ? VK_LValue - :Type->getType()->isRValueReferenceType()? VK_XValue - :VK_RValue), - OK_Ordinary, - Type->getType()->isDependentType() || - Type->getType()->getContainedDeducedType(), - true, true, - Type->getType()->containsUnexpandedParameterPack()), - Type(Type), - LParenLoc(LParenLoc), - RParenLoc(RParenLoc), - NumArgs(Args.size()) { + : Expr(CXXUnresolvedConstructExprClass, + Type->getType().getNonReferenceType(), + (Type->getType()->isLValueReferenceType() + ? VK_LValue + : Type->getType()->isRValueReferenceType() ? VK_XValue + : VK_RValue), + OK_Ordinary, + Type->getType()->isDependentType() || + Type->getType()->getContainedDeducedType(), + true, true, Type->getType()->containsUnexpandedParameterPack()), + Type(Type), LParenLoc(LParenLoc), RParenLoc(RParenLoc), + NumArgs(Args.size()) { Expr **StoredArgs = getTrailingObjects<Expr *>(); for (unsigned I = 0; I != Args.size(); ++I) { if (Args[I]->containsUnexpandedParameterPack()) @@ -1159,7 +1178,7 @@ CXXDependentScopeMemberExpr::CreateEmpty(const ASTContext &C, void *Mem = C.Allocate(Size, alignof(CXXDependentScopeMemberExpr)); CXXDependentScopeMemberExpr *E = new (Mem) CXXDependentScopeMemberExpr(C, nullptr, QualType(), - 0, SourceLocation(), + false, SourceLocation(), NestedNameSpecifierLoc(), SourceLocation(), nullptr, DeclarationNameInfo(), nullptr); @@ -1202,19 +1221,18 @@ UnresolvedMemberExpr::UnresolvedMemberExpr(const ASTContext &C, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End) - : OverloadExpr(UnresolvedMemberExprClass, C, QualifierLoc, TemplateKWLoc, - MemberNameInfo, TemplateArgs, Begin, End, - // Dependent - ((Base && Base->isTypeDependent()) || - BaseType->isDependentType()), - ((Base && Base->isInstantiationDependent()) || - BaseType->isInstantiationDependentType()), - // Contains unexpanded parameter pack - ((Base && Base->containsUnexpandedParameterPack()) || - BaseType->containsUnexpandedParameterPack())), - IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing), - Base(Base), BaseType(BaseType), OperatorLoc(OperatorLoc) { - + : OverloadExpr( + UnresolvedMemberExprClass, C, QualifierLoc, TemplateKWLoc, + MemberNameInfo, TemplateArgs, Begin, End, + // Dependent + ((Base && Base->isTypeDependent()) || BaseType->isDependentType()), + ((Base && Base->isInstantiationDependent()) || + BaseType->isInstantiationDependentType()), + // Contains unexpanded parameter pack + ((Base && Base->containsUnexpandedParameterPack()) || + BaseType->containsUnexpandedParameterPack())), + IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing), Base(Base), + BaseType(BaseType), OperatorLoc(OperatorLoc) { // Check whether all of the members are non-static member functions, // and if so, mark give this bound-member type instead of overload type. if (hasOnlyNonStaticMemberFunctions(Begin, End)) @@ -1315,10 +1333,10 @@ SubstNonTypeTemplateParmPackExpr(QualType T, NonTypeTemplateParmDecl *Param, SourceLocation NameLoc, const TemplateArgument &ArgPack) - : Expr(SubstNonTypeTemplateParmPackExprClass, T, VK_RValue, OK_Ordinary, - true, true, true, true), - Param(Param), Arguments(ArgPack.pack_begin()), - NumArguments(ArgPack.pack_size()), NameLoc(NameLoc) { } + : Expr(SubstNonTypeTemplateParmPackExprClass, T, VK_RValue, OK_Ordinary, + true, true, true, true), + Param(Param), Arguments(ArgPack.pack_begin()), + NumArguments(ArgPack.pack_size()), NameLoc(NameLoc) {} TemplateArgument SubstNonTypeTemplateParmPackExpr::getArgumentPack() const { return TemplateArgument(llvm::makeArrayRef(Arguments, NumArguments)); @@ -1374,13 +1392,12 @@ TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind, ArrayRef<TypeSourceInfo *> Args, SourceLocation RParenLoc, bool Value) - : Expr(TypeTraitExprClass, T, VK_RValue, OK_Ordinary, - /*TypeDependent=*/false, - /*ValueDependent=*/false, - /*InstantiationDependent=*/false, - /*ContainsUnexpandedParameterPack=*/false), - Loc(Loc), RParenLoc(RParenLoc) -{ + : Expr(TypeTraitExprClass, T, VK_RValue, OK_Ordinary, + /*TypeDependent=*/false, + /*ValueDependent=*/false, + /*InstantiationDependent=*/false, + /*ContainsUnexpandedParameterPack=*/false), + Loc(Loc), RParenLoc(RParenLoc) { TypeTraitExprBits.Kind = Kind; TypeTraitExprBits.Value = Value; TypeTraitExprBits.NumArgs = Args.size(); @@ -1415,4 +1432,4 @@ TypeTraitExpr *TypeTraitExpr::CreateDeserialized(const ASTContext &C, return new (Mem) TypeTraitExpr(EmptyShell()); } -void ArrayTypeTraitExpr::anchor() { } +void ArrayTypeTraitExpr::anchor() {} diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index d149bdd0cdf9..3bb2b4eb5fc1 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -641,7 +641,7 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, // Records with any const fields (recursively) are not modifiable. if (const RecordType *R = CT->getAs<RecordType>()) if (R->hasConstFields()) - return Cl::CM_ConstQualified; + return Cl::CM_ConstQualifiedField; return Cl::CM_Modifiable; } @@ -695,6 +695,7 @@ Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const { llvm_unreachable("CM_LValueCast and CL_LValue don't match"); case Cl::CM_NoSetterProperty: return MLV_NoSetterProperty; case Cl::CM_ConstQualified: return MLV_ConstQualified; + case Cl::CM_ConstQualifiedField: return MLV_ConstQualifiedField; case Cl::CM_ConstAddrSpace: return MLV_ConstAddrSpace; case Cl::CM_ArrayType: return MLV_ArrayType; case Cl::CM_IncompleteType: return MLV_IncompleteType; diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 792e8cc4a518..9c9eeb79b40a 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -62,7 +62,13 @@ namespace { static QualType getType(APValue::LValueBase B) { if (!B) return QualType(); if (const ValueDecl *D = B.dyn_cast<const ValueDecl*>()) - return D->getType(); + // FIXME: It's unclear where we're supposed to take the type from, and + // this actually matters for arrays of unknown bound. Using the type of + // the most recent declaration isn't clearly correct in general. Eg: + // + // extern int arr[]; void f() { extern int arr[3]; }; + // constexpr int *p = &arr[1]; // valid? + return cast<ValueDecl>(D->getMostRecentDecl())->getType(); const Expr *Base = B.get<const Expr*>(); @@ -141,6 +147,12 @@ namespace { return E && E->getType()->isPointerType() && tryUnwrapAllocSizeCall(E); } + /// The bound to claim that an array of unknown bound has. + /// The value in MostDerivedArraySize is undefined in this case. So, set it + /// to an arbitrary value that's likely to loudly break things if it's used. + static const uint64_t AssumedSizeForUnsizedArray = + std::numeric_limits<uint64_t>::max() / 2; + /// Determines if an LValue with the given LValueBase will have an unsized /// array in its designator. /// Find the path length and type of the most-derived subobject in the given @@ -148,7 +160,8 @@ namespace { static unsigned findMostDerivedSubobject(ASTContext &Ctx, APValue::LValueBase Base, ArrayRef<APValue::LValuePathEntry> Path, - uint64_t &ArraySize, QualType &Type, bool &IsArray) { + uint64_t &ArraySize, QualType &Type, bool &IsArray, + bool &FirstEntryIsUnsizedArray) { // This only accepts LValueBases from APValues, and APValues don't support // arrays that lack size info. assert(!isBaseAnAllocSizeCall(Base) && @@ -158,12 +171,18 @@ namespace { for (unsigned I = 0, N = Path.size(); I != N; ++I) { if (Type->isArrayType()) { - const ConstantArrayType *CAT = - cast<ConstantArrayType>(Ctx.getAsArrayType(Type)); - Type = CAT->getElementType(); - ArraySize = CAT->getSize().getZExtValue(); + const ArrayType *AT = Ctx.getAsArrayType(Type); + Type = AT->getElementType(); MostDerivedLength = I + 1; IsArray = true; + + if (auto *CAT = dyn_cast<ConstantArrayType>(AT)) { + ArraySize = CAT->getSize().getZExtValue(); + } else { + assert(I == 0 && "unexpected unsized array designator"); + FirstEntryIsUnsizedArray = true; + ArraySize = AssumedSizeForUnsizedArray; + } } else if (Type->isAnyComplexType()) { const ComplexType *CT = Type->castAs<ComplexType>(); Type = CT->getElementType(); @@ -246,10 +265,12 @@ namespace { Entries.insert(Entries.end(), VEntries.begin(), VEntries.end()); if (V.getLValueBase()) { bool IsArray = false; + bool FirstIsUnsizedArray = false; MostDerivedPathLength = findMostDerivedSubobject( Ctx, V.getLValueBase(), V.getLValuePath(), MostDerivedArraySize, - MostDerivedType, IsArray); + MostDerivedType, IsArray, FirstIsUnsizedArray); MostDerivedIsArrayElement = IsArray; + FirstEntryIsAnUnsizedArray = FirstIsUnsizedArray; } } } @@ -318,7 +339,7 @@ namespace { // The value in MostDerivedArraySize is undefined in this case. So, set it // to an arbitrary value that's likely to loudly break things if it's // used. - MostDerivedArraySize = std::numeric_limits<uint64_t>::max() / 2; + MostDerivedArraySize = AssumedSizeForUnsizedArray; MostDerivedPathLength = Entries.size(); } /// Update this designator to refer to the given base or member of this @@ -350,6 +371,7 @@ namespace { MostDerivedArraySize = 2; MostDerivedPathLength = Entries.size(); } + void diagnoseUnsizedArrayPointerArithmetic(EvalInfo &Info, const Expr *E); void diagnosePointerArithmetic(EvalInfo &Info, const Expr *E, const APSInt &N); /// Add N to the address of this subobject. @@ -357,6 +379,7 @@ namespace { if (Invalid || !N) return; uint64_t TruncatedN = N.extOrTrunc(64).getZExtValue(); if (isMostDerivedAnUnsizedArray()) { + diagnoseUnsizedArrayPointerArithmetic(Info, E); // Can't verify -- trust that the user is doing the right thing (or if // not, trust that the caller will catch the bad behavior). // FIXME: Should we reject if this overflows, at least? @@ -573,6 +596,31 @@ namespace { /// declaration whose initializer is being evaluated, if any. APValue *EvaluatingDeclValue; + /// EvaluatingObject - Pair of the AST node that an lvalue represents and + /// the call index that that lvalue was allocated in. + typedef std::pair<APValue::LValueBase, unsigned> EvaluatingObject; + + /// EvaluatingConstructors - Set of objects that are currently being + /// constructed. + llvm::DenseSet<EvaluatingObject> EvaluatingConstructors; + + struct EvaluatingConstructorRAII { + EvalInfo &EI; + EvaluatingObject Object; + bool DidInsert; + EvaluatingConstructorRAII(EvalInfo &EI, EvaluatingObject Object) + : EI(EI), Object(Object) { + DidInsert = EI.EvaluatingConstructors.insert(Object).second; + } + ~EvaluatingConstructorRAII() { + if (DidInsert) EI.EvaluatingConstructors.erase(Object); + } + }; + + bool isEvaluatingConstructor(APValue::LValueBase Decl, unsigned CallIndex) { + return EvaluatingConstructors.count(EvaluatingObject(Decl, CallIndex)); + } + /// The current array initialization index, if we're performing array /// initialization. uint64_t ArrayInitIndex = -1; @@ -666,6 +714,7 @@ namespace { void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) { EvaluatingDecl = Base; EvaluatingDeclValue = &Value; + EvaluatingConstructors.insert({Base, 0}); } const LangOptions &getLangOpts() const { return Ctx.getLangOpts(); } @@ -984,6 +1033,7 @@ namespace { void moveFromAndCancel(SpeculativeEvaluationRAII &&Other) { Info = Other.Info; OldStatus = Other.OldStatus; + OldIsSpeculativelyEvaluating = Other.OldIsSpeculativelyEvaluating; Other.Info = nullptr; } @@ -1067,9 +1117,19 @@ bool SubobjectDesignator::checkSubobject(EvalInfo &Info, const Expr *E, setInvalid(); return false; } + // Note, we do not diagnose if isMostDerivedAnUnsizedArray(), because there + // must actually be at least one array element; even a VLA cannot have a + // bound of zero. And if our index is nonzero, we already had a CCEDiag. return true; } +void SubobjectDesignator::diagnoseUnsizedArrayPointerArithmetic(EvalInfo &Info, + const Expr *E) { + Info.CCEDiag(E, diag::note_constexpr_unsized_array_indexed); + // Do not set the designator as invalid: we can represent this situation, + // and correct handling of __builtin_object_size requires us to do so. +} + void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info, const Expr *E, const APSInt &N) { @@ -1213,8 +1273,6 @@ namespace { IsNullPtr); else { assert(!InvalidBase && "APValues can't handle invalid LValue bases"); - assert(!Designator.FirstEntryIsAnUnsizedArray && - "Unsized array with a valid base?"); V = APValue(Base, Offset, Designator.Entries, Designator.IsOnePastTheEnd, CallIndex, IsNullPtr); } @@ -1287,12 +1345,17 @@ namespace { if (checkSubobject(Info, E, isa<FieldDecl>(D) ? CSK_Field : CSK_Base)) Designator.addDeclUnchecked(D, Virtual); } - void addUnsizedArray(EvalInfo &Info, QualType ElemTy) { - assert(Designator.Entries.empty() && getType(Base)->isPointerType()); - assert(isBaseAnAllocSizeCall(Base) && - "Only alloc_size bases can have unsized arrays"); - Designator.FirstEntryIsAnUnsizedArray = true; - Designator.addUnsizedArrayUnchecked(ElemTy); + void addUnsizedArray(EvalInfo &Info, const Expr *E, QualType ElemTy) { + if (!Designator.Entries.empty()) { + Info.CCEDiag(E, diag::note_constexpr_unsupported_unsized_array); + Designator.setInvalid(); + return; + } + if (checkSubobject(Info, E, CSK_ArrayToPointer)) { + assert(getType(Base)->isPointerType() || getType(Base)->isArrayType()); + Designator.FirstEntryIsAnUnsizedArray = true; + Designator.addUnsizedArrayUnchecked(ElemTy); + } } void addArray(EvalInfo &Info, const Expr *E, const ConstantArrayType *CAT) { if (checkSubobject(Info, E, CSK_ArrayToPointer)) @@ -1756,6 +1819,9 @@ static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc, } } for (const auto *I : RD->fields()) { + if (I->isUnnamedBitfield()) + continue; + if (!CheckConstantExpression(Info, DiagLoc, I->getType(), Value.getStructField(I->getFieldIndex()))) return false; @@ -2597,10 +2663,12 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, if (Sub.Invalid) // A diagnostic will have already been produced. return handler.failed(); - if (Sub.isOnePastTheEnd()) { + if (Sub.isOnePastTheEnd() || Sub.isMostDerivedAnUnsizedArray()) { if (Info.getLangOpts().CPlusPlus11) - Info.FFDiag(E, diag::note_constexpr_access_past_end) - << handler.AccessKind; + Info.FFDiag(E, Sub.isOnePastTheEnd() + ? diag::note_constexpr_access_past_end + : diag::note_constexpr_access_unsized_array) + << handler.AccessKind; else Info.FFDiag(E); return handler.failed(); @@ -3097,10 +3165,9 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, } // During the construction of an object, it is not yet 'const'. - // FIXME: We don't set up EvaluatingDecl for local variables or temporaries, - // and this doesn't do quite the right thing for const subobjects of the + // FIXME: This doesn't do quite the right thing for const subobjects of the // object under construction. - if (LVal.getLValueBase() == Info.EvaluatingDecl) { + if (Info.isEvaluatingConstructor(LVal.getLValueBase(), LVal.CallIndex)) { BaseType = Info.Ctx.getCanonicalType(BaseType); BaseType.removeLocalConst(); } @@ -4253,6 +4320,8 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This, return false; } + EvalInfo::EvaluatingConstructorRAII EvalObj( + Info, {This.getLValueBase(), This.CallIndex}); CallStackFrame Frame(Info, CallLoc, Definition, &This, ArgValues); // FIXME: Creating an APValue just to hold a nonexistent return value is @@ -5459,7 +5528,7 @@ static bool evaluateLValueAsAllocSize(EvalInfo &Info, APValue::LValueBase Base, Result.setInvalid(E); QualType Pointee = E->getType()->castAs<PointerType>()->getPointeeType(); - Result.addUnsizedArray(Info, Pointee); + Result.addUnsizedArray(Info, E, Pointee); return true; } @@ -5669,7 +5738,8 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { return true; } } - case CK_ArrayToPointerDecay: + + case CK_ArrayToPointerDecay: { if (SubExpr->isGLValue()) { if (!evaluateLValue(SubExpr, Result)) return false; @@ -5680,12 +5750,13 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { return false; } // The result is a pointer to the first element of the array. - if (const ConstantArrayType *CAT - = Info.Ctx.getAsConstantArrayType(SubExpr->getType())) + auto *AT = Info.Ctx.getAsArrayType(SubExpr->getType()); + if (auto *CAT = dyn_cast<ConstantArrayType>(AT)) Result.addArray(Info, E, CAT); else - Result.Designator.setInvalid(); + Result.addUnsizedArray(Info, E, AT->getElementType()); return true; + } case CK_FunctionToPointerDecay: return evaluateLValue(SubExpr, Result); @@ -5752,7 +5823,7 @@ bool PointerExprEvaluator::visitNonBuiltinCallExpr(const CallExpr *E) { Result.setInvalid(E); QualType PointeeTy = E->getType()->castAs<PointerType>()->getPointeeType(); - Result.addUnsizedArray(Info, PointeeTy); + Result.addUnsizedArray(Info, E, PointeeTy); return true; } @@ -7313,7 +7384,8 @@ static const Expr *ignorePointerCastsAndParens(const Expr *E) { /// Please note: this function is specialized for how __builtin_object_size /// views "objects". /// -/// If this encounters an invalid RecordDecl, it will always return true. +/// If this encounters an invalid RecordDecl or otherwise cannot determine the +/// correct result, it will always return true. static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) { assert(!LVal.Designator.Invalid); @@ -7344,9 +7416,8 @@ static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) { unsigned I = 0; QualType BaseType = getType(Base); if (LVal.Designator.FirstEntryIsAnUnsizedArray) { - assert(isBaseAnAllocSizeCall(Base) && - "Unsized array in non-alloc_size call?"); - // If this is an alloc_size base, we should ignore the initial array index + // If we don't know the array bound, conservatively assume we're looking at + // the final array element. ++I; BaseType = BaseType->castAs<PointerType>()->getPointeeType(); } @@ -7901,6 +7972,9 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, return BuiltinOp == Builtin::BI__atomic_always_lock_free ? Success(0, E) : Error(E); } + case Builtin::BIomp_is_initial_device: + // We can decide statically which value the runtime would return if called. + return Success(Info.getLangOpts().OpenMPIsDevice ? 0 : 1, E); } } @@ -10397,6 +10471,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case BO_AndAssign: case BO_XorAssign: case BO_OrAssign: + case BO_Cmp: // FIXME: Re-enable once we can evaluate this. // C99 6.6/3 allows assignments within unevaluated subexpressions of // constant expressions, but they can never be ICEs because an ICE cannot // contain an lvalue operand. diff --git a/lib/AST/ExprObjC.cpp b/lib/AST/ExprObjC.cpp index 31c1b3f15621..e1a23f598589 100644 --- a/lib/AST/ExprObjC.cpp +++ b/lib/AST/ExprObjC.cpp @@ -1,4 +1,4 @@ -//===--- ExprObjC.cpp - (ObjC) Expression AST Node Implementation ---------===// +//===- ExprObjC.cpp - (ObjC) Expression AST Node Implementation -----------===// // // The LLVM Compiler Infrastructure // @@ -12,8 +12,15 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ExprObjC.h" - #include "clang/AST/ASTContext.h" +#include "clang/AST/SelectorLocationsKind.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeLoc.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ErrorHandling.h" +#include <algorithm> +#include <cassert> +#include <cstdint> using namespace clang; @@ -45,7 +52,6 @@ ObjCArrayLiteral *ObjCArrayLiteral::Create(const ASTContext &C, ObjCArrayLiteral *ObjCArrayLiteral::CreateEmpty(const ASTContext &C, unsigned NumElements) { - void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumElements)); return new (Mem) ObjCArrayLiteral(EmptyShell(), NumElements); } diff --git a/lib/AST/ExternalASTMerger.cpp b/lib/AST/ExternalASTMerger.cpp index 4f4a99794c5b..6b75c51c6420 100644 --- a/lib/AST/ExternalASTMerger.cpp +++ b/lib/AST/ExternalASTMerger.cpp @@ -14,6 +14,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ExternalASTMerger.h" @@ -32,26 +33,18 @@ template <typename T> struct Source { 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); - } -}; +/// For the given DC, return the DC that is safe to perform lookups on. This is +/// the DC we actually want to work with most of the time. +const DeclContext *CanonicalizeDC(const DeclContext *DC) { + if (isa<LinkageSpecDecl>(DC)) + return DC->getRedeclContext(); + return DC; +} Source<const DeclContext *> LookupSameContext(Source<TranslationUnitDecl *> SourceTU, const DeclContext *DC, ASTImporter &ReverseImporter) { + DC = CanonicalizeDC(DC); if (DC->isTranslationUnit()) { return SourceTU; } @@ -61,100 +54,328 @@ LookupSameContext(Source<TranslationUnitDecl *> SourceTU, const DeclContext *DC, // If we couldn't find the parent DC in this TranslationUnit, give up. return nullptr; } - auto ND = cast<NamedDecl>(DC); + 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 + if (SearchResultSize == 0 || SearchResultSize > 1) { + // There are two cases here. First, we might not find the name. + // We might also find multiple copies, in which case we have no + // guarantee that the one we wanted is the one we pick. (E.g., + // if we have two specializations of the same template it is + // very hard to determine which is the one you want.) + // + // The Origins map fixes this problem by allowing the origin to be + // explicitly recorded, so we trigger that recording by returning + // nothing (rather than a possibly-inaccurate guess) here. return nullptr; } else { NamedDecl *SearchResultDecl = SearchResult[0]; - return dyn_cast<DeclContext>(SearchResultDecl); + if (isa<DeclContext>(SearchResultDecl) && + SearchResultDecl->getKind() == DC->getDeclKind()) + return cast<DeclContext>(SearchResultDecl)->getPrimaryContext(); + return nullptr; // This type of lookup is unsupported } } -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; - } -} +/// A custom implementation of ASTImporter, for ExternalASTMerger's purposes. +/// +/// There are several modifications: +/// +/// - It enables lazy lookup (via the HasExternalLexicalStorage flag and a few +/// others), which instructs Clang to refer to ExternalASTMerger. Also, it +/// forces MinimalImport to true, which is necessary to make this work. +/// - It maintains a reverse importer for use with names. This allows lookup of +/// arbitrary names in the source context. +/// - It updates the ExternalASTMerger's origin map as needed whenever a +/// it sees a DeclContext. +class LazyASTImporter : public ASTImporter { +private: + ExternalASTMerger &Parent; + ASTImporter Reverse; + const ExternalASTMerger::OriginMap &FromOrigins; -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); + llvm::raw_ostream &logs() { return Parent.logs(); } +public: + LazyASTImporter(ExternalASTMerger &_Parent, ASTContext &ToContext, + FileManager &ToFileManager, ASTContext &FromContext, + FileManager &FromFileManager, + const ExternalASTMerger::OriginMap &_FromOrigins) + : ASTImporter(ToContext, ToFileManager, FromContext, FromFileManager, + /*MinimalImport=*/true), + Parent(_Parent), Reverse(FromContext, FromFileManager, ToContext, + ToFileManager, /*MinimalImport=*/true), FromOrigins(_FromOrigins) {} + + /// Whenever a DeclContext is imported, ensure that ExternalASTSource's origin + /// map is kept up to date. Also set the appropriate flags. + Decl *Imported(Decl *From, Decl *To) override { + if (auto *ToDC = dyn_cast<DeclContext>(To)) { + const bool LoggingEnabled = Parent.LoggingEnabled(); + if (LoggingEnabled) + logs() << "(ExternalASTMerger*)" << (void*)&Parent + << " imported (DeclContext*)" << (void*)ToDC + << ", (ASTContext*)" << (void*)&getToContext() + << " from (DeclContext*)" << (void*)llvm::cast<DeclContext>(From) + << ", (ASTContext*)" << (void*)&getFromContext() + << "\n"; + Source<DeclContext *> FromDC( + cast<DeclContext>(From)->getPrimaryContext()); + if (FromOrigins.count(FromDC) && + Parent.HasImporterForOrigin(*FromOrigins.at(FromDC).AST)) { + if (LoggingEnabled) + logs() << "(ExternalASTMerger*)" << (void*)&Parent + << " forced origin (DeclContext*)" + << (void*)FromOrigins.at(FromDC).DC + << ", (ASTContext*)" + << (void*)FromOrigins.at(FromDC).AST + << "\n"; + Parent.ForceRecordOrigin(ToDC, FromOrigins.at(FromDC)); + } else { + if (LoggingEnabled) + logs() << "(ExternalASTMerger*)" << (void*)&Parent + << " maybe recording origin (DeclContext*)" << (void*)FromDC + << ", (ASTContext*)" << (void*)&getFromContext() + << "\n"; + Parent.MaybeRecordOrigin(ToDC, {FromDC, &getFromContext()}); + } + } + if (auto *ToTag = dyn_cast<TagDecl>(To)) { + ToTag->setHasExternalLexicalStorage(); + ToTag->setMustBuildLookupTable(); + assert(Parent.CanComplete(ToTag)); + } else if (auto *ToNamespace = dyn_cast<NamespaceDecl>(To)) { + ToNamespace->setHasExternalVisibleStorage(); + assert(Parent.CanComplete(ToNamespace)); + } else if (auto *ToContainer = dyn_cast<ObjCContainerDecl>(To)) { + ToContainer->setHasExternalLexicalStorage(); + ToContainer->setMustBuildLookupTable(); + assert(Parent.CanComplete(ToContainer)); + } + return ASTImporter::Imported(From, To); } -} + ASTImporter &GetReverse() { return Reverse; } +}; bool HasDeclOfSameType(llvm::ArrayRef<Candidate> Decls, const Candidate &C) { + if (isa<FunctionDecl>(C.first.get())) + return false; 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)}); - } +ASTImporter &ExternalASTMerger::ImporterForOrigin(ASTContext &OriginContext) { + for (const std::unique_ptr<ASTImporter> &I : Importers) + if (&I->getFromContext() == &OriginContext) + return *I; + llvm_unreachable("We should have an importer for this origin!"); } -bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC, - DeclarationName Name) { - llvm::SmallVector<NamedDecl *, 1> Decls; - llvm::SmallVector<Candidate, 4> CompleteDecls; - llvm::SmallVector<Candidate, 4> ForwardDecls; +namespace { +LazyASTImporter &LazyImporterForOrigin(ExternalASTMerger &Merger, + ASTContext &OriginContext) { + return static_cast<LazyASTImporter &>( + Merger.ImporterForOrigin(OriginContext)); +} +} - auto FilterFoundDecl = [&CompleteDecls, &ForwardDecls](const Candidate &C) { - if (IsForwardDeclaration(C.first.get())) { - if (!HasDeclOfSameType(ForwardDecls, C)) { - ForwardDecls.push_back(C); +bool ExternalASTMerger::HasImporterForOrigin(ASTContext &OriginContext) { + for (const std::unique_ptr<ASTImporter> &I : Importers) + if (&I->getFromContext() == &OriginContext) + return true; + return false; +} + +template <typename CallbackType> +void ExternalASTMerger::ForEachMatchingDC(const DeclContext *DC, + CallbackType Callback) { + if (Origins.count(DC)) { + ExternalASTMerger::DCOrigin Origin = Origins[DC]; + LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST); + Callback(Importer, Importer.GetReverse(), Origin.DC); + } else { + bool DidCallback = false; + for (const std::unique_ptr<ASTImporter> &Importer : Importers) { + Source<TranslationUnitDecl *> SourceTU = + Importer->getFromContext().getTranslationUnitDecl(); + ASTImporter &Reverse = + static_cast<LazyASTImporter *>(Importer.get())->GetReverse(); + if (auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) { + DidCallback = true; + if (Callback(*Importer, Reverse, SourceDC)) + break; } - } else { - CompleteDecls.push_back(C); } - }; + if (!DidCallback && LoggingEnabled()) + logs() << "(ExternalASTMerger*)" << (void*)this + << " asserting for (DeclContext*)" << (const void*)DC + << ", (ASTContext*)" << (void*)&Target.AST + << "\n"; + assert(DidCallback && "Couldn't find a source context matching our DC"); + } +} + +void ExternalASTMerger::CompleteType(TagDecl *Tag) { + assert(Tag->hasExternalLexicalStorage()); + ForEachMatchingDC(Tag, [&](ASTImporter &Forward, ASTImporter &Reverse, + Source<const DeclContext *> SourceDC) -> bool { + auto *SourceTag = const_cast<TagDecl *>(cast<TagDecl>(SourceDC.get())); + if (SourceTag->hasExternalLexicalStorage()) + SourceTag->getASTContext().getExternalSource()->CompleteType(SourceTag); + if (!SourceTag->getDefinition()) + return false; + Forward.Imported(SourceTag, Tag); + Forward.ImportDefinition(SourceTag); + Tag->setCompleteDefinition(SourceTag->isCompleteDefinition()); + return true; + }); +} +void ExternalASTMerger::CompleteType(ObjCInterfaceDecl *Interface) { + assert(Interface->hasExternalLexicalStorage()); 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())); - } + Interface, [&](ASTImporter &Forward, ASTImporter &Reverse, + Source<const DeclContext *> SourceDC) -> bool { + auto *SourceInterface = const_cast<ObjCInterfaceDecl *>( + cast<ObjCInterfaceDecl>(SourceDC.get())); + if (SourceInterface->hasExternalLexicalStorage()) + SourceInterface->getASTContext().getExternalSource()->CompleteType( + SourceInterface); + if (!SourceInterface->getDefinition()) + return false; + Forward.Imported(SourceInterface, Interface); + Forward.ImportDefinition(SourceInterface); + return true; }); +} - llvm::ArrayRef<Candidate> DeclsToReport = - CompleteDecls.empty() ? ForwardDecls : CompleteDecls; +bool ExternalASTMerger::CanComplete(DeclContext *Interface) { + assert(Interface->hasExternalLexicalStorage() || + Interface->hasExternalVisibleStorage()); + bool FoundMatchingDC = false; + ForEachMatchingDC(Interface, + [&](ASTImporter &Forward, ASTImporter &Reverse, + Source<const DeclContext *> SourceDC) -> bool { + FoundMatchingDC = true; + return true; + }); + return FoundMatchingDC; +} - if (DeclsToReport.empty()) { - return false; +namespace { +bool IsSameDC(const DeclContext *D1, const DeclContext *D2) { + if (isa<ObjCContainerDecl>(D1) && isa<ObjCContainerDecl>(D2)) + return true; // There are many cases where Objective-C is ambiguous. + if (auto *T1 = dyn_cast<TagDecl>(D1)) + if (auto *T2 = dyn_cast<TagDecl>(D2)) + if (T1->getFirstDecl() == T2->getFirstDecl()) + return true; + return D1 == D2 || D1 == CanonicalizeDC(D2); +} +} + +void ExternalASTMerger::MaybeRecordOrigin(const DeclContext *ToDC, + DCOrigin Origin) { + LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST); + ASTImporter &Reverse = Importer.GetReverse(); + Source<const DeclContext *> FoundFromDC = + LookupSameContext(Origin.AST->getTranslationUnitDecl(), ToDC, Reverse); + const bool DoRecord = !FoundFromDC || !IsSameDC(FoundFromDC.get(), Origin.DC); + if (DoRecord) + RecordOriginImpl(ToDC, Origin, Importer); + if (LoggingEnabled()) + logs() << "(ExternalASTMerger*)" << (void*)this + << (DoRecord ? " decided " : " decided NOT") + << " to record origin (DeclContext*)" << (void*)Origin.DC + << ", (ASTContext*)" << (void*)&Origin.AST + << "\n"; +} + +void ExternalASTMerger::ForceRecordOrigin(const DeclContext *ToDC, + DCOrigin Origin) { + RecordOriginImpl(ToDC, Origin, ImporterForOrigin(*Origin.AST)); +} + +void ExternalASTMerger::RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin, + ASTImporter &Importer) { + Origins[ToDC] = Origin; + Importer.ASTImporter::Imported(cast<Decl>(Origin.DC), const_cast<Decl*>(cast<Decl>(ToDC))); +} + +ExternalASTMerger::ExternalASTMerger(const ImporterTarget &Target, + llvm::ArrayRef<ImporterSource> Sources) : LogStream(&llvm::nulls()), Target(Target) { + AddSources(Sources); +} + +void ExternalASTMerger::AddSources(llvm::ArrayRef<ImporterSource> Sources) { + for (const ImporterSource &S : Sources) { + assert(&S.AST != &Target.AST); + Importers.push_back(llvm::make_unique<LazyASTImporter>( + *this, Target.AST, Target.FM, S.AST, S.FM, S.OM)); + } +} + +void ExternalASTMerger::RemoveSources(llvm::ArrayRef<ImporterSource> Sources) { + if (LoggingEnabled()) + for (const ImporterSource &S : Sources) + logs() << "(ExternalASTMerger*)" << (void*)this + << " removing source (ASTContext*)" << (void*)&S.AST + << "\n"; + Importers.erase( + std::remove_if(Importers.begin(), Importers.end(), + [&Sources](std::unique_ptr<ASTImporter> &Importer) -> bool { + for (const ImporterSource &S : Sources) { + if (&Importer->getFromContext() == &S.AST) + return true; + } + return false; + }), + Importers.end()); + for (OriginMap::iterator OI = Origins.begin(), OE = Origins.end(); OI != OE; ) { + std::pair<const DeclContext *, DCOrigin> Origin = *OI; + bool Erase = false; + for (const ImporterSource &S : Sources) { + if (&S.AST == Origin.second.AST) { + Erase = true; + break; + } + } + if (Erase) + OI = Origins.erase(OI); + else + ++OI; } +} + +bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC, + DeclarationName Name) { + llvm::SmallVector<NamedDecl *, 1> Decls; + llvm::SmallVector<Candidate, 4> Candidates; + + auto FilterFoundDecl = [&Candidates](const Candidate &C) { + if (!HasDeclOfSameType(Candidates, C)) + Candidates.push_back(C); + }; + + ForEachMatchingDC(DC, [&](ASTImporter &Forward, ASTImporter &Reverse, + Source<const DeclContext *> SourceDC) -> bool { + DeclarationName FromName = Reverse.Import(Name); + DeclContextLookupResult Result = SourceDC.get()->lookup(FromName); + for (NamedDecl *FromD : Result) { + FilterFoundDecl(std::make_pair(FromD, &Forward)); + } + return false; + }); - Decls.reserve(DeclsToReport.size()); - for (const Candidate &C : DeclsToReport) { + if (Candidates.empty()) + return false; + + Decls.reserve(Candidates.size()); + for (const Candidate &C : Candidates) { NamedDecl *d = cast<NamedDecl>(C.second->Import(C.first.get())); assert(d); Decls.push_back(d); @@ -166,17 +387,16 @@ bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC, 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; - } - } - }); + ForEachMatchingDC(DC, [&](ASTImporter &Forward, ASTImporter &Reverse, + Source<const DeclContext *> SourceDC) -> bool { + for (const Decl *SourceDecl : SourceDC.get()->decls()) { + if (IsKindWeWant(SourceDecl->getKind())) { + Decl *ImportedDecl = Forward.Import(const_cast<Decl *>(SourceDecl)); + assert(!ImportedDecl || IsSameDC(ImportedDecl->getDeclContext(), DC)); + (void)ImportedDecl; + } + } + return false; + }); } diff --git a/lib/AST/ExternalASTSource.cpp b/lib/AST/ExternalASTSource.cpp index 182d38242f59..198ba9d4fbdb 100644 --- a/lib/AST/ExternalASTSource.cpp +++ b/lib/AST/ExternalASTSource.cpp @@ -1,4 +1,4 @@ -//===- ExternalASTSource.cpp - Abstract External AST Interface --*- C++ -*-===// +//===- ExternalASTSource.cpp - Abstract External AST Interface ------------===// // // The LLVM Compiler Infrastructure // @@ -16,12 +16,16 @@ #include "clang/AST/ExternalASTSource.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclarationName.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/Module.h" +#include "llvm/ADT/None.h" #include "llvm/Support/ErrorHandling.h" +#include <cstdint> using namespace clang; -ExternalASTSource::~ExternalASTSource() { } +ExternalASTSource::~ExternalASTSource() = default; llvm::Optional<ExternalASTSource::ASTSourceDescriptor> ExternalASTSource::getSourceDescriptor(unsigned ID) { @@ -66,7 +70,7 @@ void ExternalASTSource::FinishedDeserializing() {} void ExternalASTSource::StartTranslationUnit(ASTConsumer *Consumer) {} -void ExternalASTSource::PrintStats() { } +void ExternalASTSource::PrintStats() {} bool ExternalASTSource::layoutRecordType( const RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, diff --git a/lib/AST/ItaniumCXXABI.cpp b/lib/AST/ItaniumCXXABI.cpp index 692a455eafc0..d6bc16b6350f 100644 --- a/lib/AST/ItaniumCXXABI.cpp +++ b/lib/AST/ItaniumCXXABI.cpp @@ -101,15 +101,17 @@ protected: public: ItaniumCXXABI(ASTContext &Ctx) : Context(Ctx) { } - std::pair<uint64_t, unsigned> - getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const override { + MemberPointerInfo + getMemberPointerInfo(const MemberPointerType *MPT) const override { const TargetInfo &Target = Context.getTargetInfo(); TargetInfo::IntType PtrDiff = Target.getPtrDiffType(0); - uint64_t Width = Target.getTypeWidth(PtrDiff); - unsigned Align = Target.getTypeAlign(PtrDiff); + MemberPointerInfo MPI; + MPI.Width = Target.getTypeWidth(PtrDiff); + MPI.Align = Target.getTypeAlign(PtrDiff); + MPI.HasPadding = false; if (MPT->isMemberFunctionPointer()) - Width = 2 * Width; - return std::make_pair(Width, Align); + MPI.Width *= 2; + return MPI; } CallingConv getDefaultMethodCallConv(bool isVariadic) const override { diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 4e7c6c4edf37..f95dc8458e8a 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -11,7 +11,7 @@ // which is used in GCC 3.2 and newer (and many compilers that are // ABI-compatible with GCC): // -// http://mentorembedded.github.io/cxx-abi/abi.html#mangling +// http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling // //===----------------------------------------------------------------------===// #include "clang/AST/Mangle.h" @@ -381,6 +381,7 @@ class CXXNameMangler { AbiTagState AbiTagsRoot; llvm::DenseMap<uintptr_t, unsigned> Substitutions; + llvm::DenseMap<StringRef, unsigned> ModuleSubstitutions; ASTContext &getASTContext() const { return Context.getASTContext(); } @@ -475,6 +476,8 @@ private: void mangleNameWithAbiTags(const NamedDecl *ND, const AbiTagList *AdditionalAbiTags); + void mangleModuleName(const Module *M); + void mangleModuleNamePrefix(StringRef Name); void mangleTemplateName(const TemplateDecl *TD, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs); @@ -517,7 +520,7 @@ private: void mangleOperatorName(DeclarationName Name, unsigned Arity); void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity); void mangleVendorQualifier(StringRef qualifier); - void mangleQualifiers(Qualifiers Quals); + void mangleQualifiers(Qualifiers Quals, const DependentAddressSpaceType *DAST = nullptr); void mangleRefQualifier(RefQualifierKind RefQualifier); void mangleObjCMethodName(const ObjCMethodDecl *MD); @@ -845,9 +848,9 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { void CXXNameMangler::mangleNameWithAbiTags(const NamedDecl *ND, const AbiTagList *AdditionalAbiTags) { - // <name> ::= <nested-name> - // ::= <unscoped-name> - // ::= <unscoped-template-name> <template-args> + // <name> ::= [<module-name>] <nested-name> + // ::= [<module-name>] <unscoped-name> + // ::= [<module-name>] <unscoped-template-name> <template-args> // ::= <local-name> // const DeclContext *DC = getEffectiveDeclContext(ND); @@ -866,6 +869,19 @@ void CXXNameMangler::mangleNameWithAbiTags(const NamedDecl *ND, DC = IgnoreLinkageSpecDecls(DC); + if (isLocalContainerContext(DC)) { + mangleLocalName(ND, AdditionalAbiTags); + return; + } + + // Do not mangle the owning module for an external linkage declaration. + // This enables backwards-compatibility with non-modular code, and is + // a valid choice since conflicts are not permitted by C++ Modules TS + // [basic.def.odr]/6.2. + if (!ND->hasExternalFormalLinkage()) + if (Module *M = ND->getOwningModuleForLinkage()) + mangleModuleName(M); + if (DC->isTranslationUnit() || isStdNamespace(DC)) { // Check if we have a template. const TemplateArgumentList *TemplateArgs = nullptr; @@ -879,12 +895,42 @@ void CXXNameMangler::mangleNameWithAbiTags(const NamedDecl *ND, return; } - if (isLocalContainerContext(DC)) { - mangleLocalName(ND, AdditionalAbiTags); + mangleNestedName(ND, DC, AdditionalAbiTags); +} + +void CXXNameMangler::mangleModuleName(const Module *M) { + // Implement the C++ Modules TS name mangling proposal; see + // https://gcc.gnu.org/wiki/cxx-modules?action=AttachFile + // + // <module-name> ::= W <unscoped-name>+ E + // ::= W <module-subst> <unscoped-name>* E + Out << 'W'; + mangleModuleNamePrefix(M->Name); + Out << 'E'; +} + +void CXXNameMangler::mangleModuleNamePrefix(StringRef Name) { + // <module-subst> ::= _ <seq-id> # 0 < seq-id < 10 + // ::= W <seq-id - 10> _ # otherwise + auto It = ModuleSubstitutions.find(Name); + if (It != ModuleSubstitutions.end()) { + if (It->second < 10) + Out << '_' << static_cast<char>('0' + It->second); + else + Out << 'W' << (It->second - 10) << '_'; return; } - mangleNestedName(ND, DC, AdditionalAbiTags); + // FIXME: Preserve hierarchy in module names rather than flattening + // them to strings; use Module*s as substitution keys. + auto Parts = Name.rsplit('.'); + if (Parts.second.empty()) + Parts.second = Parts.first; + else + mangleModuleNamePrefix(Parts.first); + + Out << Parts.second.size() << Parts.second; + ModuleSubstitutions.insert({Name, ModuleSubstitutions.size()}); } void CXXNameMangler::mangleTemplateName(const TemplateDecl *TD, @@ -1233,14 +1279,23 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, } if (II) { - // We must avoid conflicts between internally- and externally- - // linked variable and function declaration names in the same TU: + // Match GCC's naming convention for internal linkage symbols, for + // symbols that are not actually visible outside of this TU. GCC + // distinguishes between internal and external linkage symbols in + // its mangling, to support cases like this that were valid C++ prior + // to DR426: + // // void test() { extern void foo(); } // static void foo(); - // This naming convention is the same as that followed by GCC, - // though it shouldn't actually matter. + // + // Don't bother with the L marker for names in anonymous namespaces; the + // 12_GLOBAL__N_1 mangling is quite sufficient there, and this better + // matches GCC anyway, because GCC does not treat anonymous namespaces as + // implying internal linkage. if (ND && ND->getFormalLinkage() == InternalLinkage && - getEffectiveDeclContext(ND)->isFileContext()) + !ND->isExternallyVisible() && + getEffectiveDeclContext(ND)->isFileContext() && + !ND->isInAnonymousNamespace()) Out << 'L'; auto *FD = dyn_cast<FunctionDecl>(ND); @@ -1620,6 +1675,10 @@ void CXXNameMangler::mangleUnqualifiedBlock(const BlockDecl *Block) { // the symbol in question isn't externally visible. if (!Number) Number = Context.getBlockId(Block, false); + else { + // Stored mangling numbers are 1-based. + --Number; + } Out << "Ub"; if (Number > 0) Out << Number - 1; @@ -1638,10 +1697,15 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { // to emit that last part of the prefix here. if (Decl *Context = Lambda->getLambdaContextDecl()) { if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) && - Context->getDeclContext()->isRecord()) { + !isa<ParmVarDecl>(Context)) { + // FIXME: 'inline auto [a, b] = []{ return ... };' does not get a + // reasonable mangling here. if (const IdentifierInfo *Name = cast<NamedDecl>(Context)->getIdentifier()) { mangleSourceName(Name); + const TemplateArgumentList *TemplateArgs = nullptr; + if (isTemplate(cast<NamedDecl>(Context), TemplateArgs)) + mangleTemplateArgs(*TemplateArgs); Out << 'M'; } } @@ -1866,6 +1930,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, case Type::IncompleteArray: case Type::VariableArray: case Type::DependentSizedArray: + case Type::DependentAddressSpace: case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: @@ -2130,6 +2195,9 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) { // Proposal on cxx-abi-dev, 2015-10-21. // ::= aw # co_await case OO_Coawait: Out << "aw"; break; + // Proposed in cxx-abi github issue 43. + // ::= ss # <=> + case OO_Spaceship: Out << "ss"; break; case OO_None: case NUM_OVERLOADED_OPERATORS: @@ -2137,10 +2205,17 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) { } } -void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { +void CXXNameMangler::mangleQualifiers(Qualifiers Quals, const DependentAddressSpaceType *DAST) { // Vendor qualifiers come first and if they are order-insensitive they must // be emitted in reversed alphabetical order, see Itanium ABI 5.1.5. + // <type> ::= U <addrspace-expr> + if (DAST) { + Out << "U2ASI"; + mangleExpression(DAST->getAddrSpaceExpr()); + Out << "E"; + } + // Address space qualifiers start with an ordinary letter. if (Quals.hasAddressSpace()) { // Address space extension: @@ -2150,20 +2225,22 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { // <type> ::= U <CUDA-addrspace> SmallString<64> ASString; - unsigned AS = Quals.getAddressSpace(); + LangAS AS = Quals.getAddressSpace(); if (Context.getASTContext().addressSpaceMapManglingFor(AS)) { // <target-addrspace> ::= "AS" <address-space-number> unsigned TargetAS = Context.getASTContext().getTargetAddressSpace(AS); - ASString = "AS" + llvm::utostr(TargetAS); + if (TargetAS != 0) + ASString = "AS" + llvm::utostr(TargetAS); } else { switch (AS) { default: llvm_unreachable("Not a language specific address space"); - // <OpenCL-addrspace> ::= "CL" [ "global" | "local" | "constant | - // "generic" ] + // <OpenCL-addrspace> ::= "CL" [ "global" | "local" | "constant" | + // "private"| "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_private: ASString = "CLprivate"; break; case LangAS::opencl_generic: ASString = "CLgeneric"; break; // <CUDA-addrspace> ::= "CU" [ "device" | "constant" | "shared" ] case LangAS::cuda_device: ASString = "CUdevice"; break; @@ -2171,7 +2248,8 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { case LangAS::cuda_shared: ASString = "CUshared"; break; } } - mangleVendorQualifier(ASString); + if (!ASString.empty()) + mangleVendorQualifier(ASString); } // The ARC ownership qualifiers start with underscores. @@ -2336,11 +2414,19 @@ void CXXNameMangler::mangleType(QualType T) { // substitution at the original type. } - if (quals) { - mangleQualifiers(quals); - // Recurse: even if the qualified type isn't yet substitutable, - // the unqualified type might be. - mangleType(QualType(ty, 0)); + if (quals || ty->isDependentAddressSpaceType()) { + if (const DependentAddressSpaceType *DAST = + dyn_cast<DependentAddressSpaceType>(ty)) { + SplitQualType splitDAST = DAST->getPointeeType().split(); + mangleQualifiers(splitDAST.Quals, DAST); + mangleType(QualType(splitDAST.Ty, 0)); + } else { + mangleQualifiers(quals); + + // Recurse: even if the qualified type isn't yet substitutable, + // the unqualified type might be. + mangleType(QualType(ty, 0)); + } } else { switch (ty->getTypeClass()) { #define ABSTRACT_TYPE(CLASS, PARENT) @@ -2392,6 +2478,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { // UNSUPPORTED: ::= De # IEEE 754r decimal floating point (128 bits) // UNSUPPORTED: ::= Df # IEEE 754r decimal floating point (32 bits) // ::= Dh # IEEE 754r half-precision floating point (16 bits) + // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point type _FloatN (N bits); // ::= Di # char32_t // ::= Ds # char16_t // ::= Dn # std::nullptr_t (i.e., decltype(nullptr)) @@ -2454,6 +2541,9 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::Int128: Out << 'n'; break; + case BuiltinType::Float16: + Out << "DF16_"; + break; case BuiltinType::Half: Out << "Dh"; break; @@ -2586,6 +2676,9 @@ CXXNameMangler::mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo PI) { if (PI.isConsumed()) mangleVendorQualifier("ns_consumed"); + + if (PI.isNoEscape()) + mangleVendorQualifier("noescape"); } // <type> ::= <function-type> @@ -2981,6 +3074,12 @@ void CXXNameMangler::mangleType(const DependentSizedExtVectorType *T) { mangleType(T->getElementType()); } +void CXXNameMangler::mangleType(const DependentAddressSpaceType *T) { + SplitQualType split = T->getPointeeType().split(); + mangleQualifiers(split.Quals, T); + mangleType(QualType(split.Ty, 0)); +} + void CXXNameMangler::mangleType(const PackExpansionType *T) { // <type> ::= Dp <type> # pack expansion (C++0x) Out << "Dp"; @@ -3343,7 +3442,6 @@ recurse: case Expr::BlockExprClass: case Expr::ChooseExprClass: case Expr::CompoundLiteralExprClass: - case Expr::DesignatedInitExprClass: case Expr::ExtVectorElementExprClass: case Expr::GenericSelectionExprClass: case Expr::ObjCEncodeExprClass: @@ -3421,6 +3519,27 @@ recurse: break; } + case Expr::DesignatedInitExprClass: { + auto *DIE = cast<DesignatedInitExpr>(E); + for (const auto &Designator : DIE->designators()) { + if (Designator.isFieldDesignator()) { + Out << "di"; + mangleSourceName(Designator.getFieldName()); + } else if (Designator.isArrayDesignator()) { + Out << "dx"; + mangleExpression(DIE->getArrayIndex(Designator)); + } else { + assert(Designator.isArrayRangeDesignator() && + "unknown designator kind"); + Out << "dX"; + mangleExpression(DIE->getArrayRangeStart(Designator)); + mangleExpression(DIE->getArrayRangeEnd(Designator)); + } + } + mangleExpression(DIE->getInit()); + break; + } + case Expr::CXXDefaultArgExprClass: mangleExpression(cast<CXXDefaultArgExpr>(E)->getExpr(), Arity); break; @@ -3512,7 +3631,6 @@ recurse: if (const Expr *Base = PDE->getBase()) mangleMemberExprBase(Base, PDE->isArrow()); NestedNameSpecifier *Qualifier = PDE->getQualifier(); - QualType ScopeType; if (TypeSourceInfo *ScopeInfo = PDE->getScopeTypeInfo()) { if (Qualifier) { mangleUnresolvedPrefix(Qualifier, @@ -3578,6 +3696,16 @@ recurse: const CXXUnresolvedConstructExpr *CE = cast<CXXUnresolvedConstructExpr>(E); unsigned N = CE->arg_size(); + if (CE->isListInitialization()) { + assert(N == 1 && "unexpected form for list initialization"); + auto *IL = cast<InitListExpr>(CE->getArg(0)); + Out << "tl"; + mangleType(CE->getType()); + mangleInitListElements(IL); + Out << "E"; + return; + } + Out << "cv"; mangleType(CE->getType()); if (N != 1) Out << '_'; @@ -4114,7 +4242,13 @@ void CXXNameMangler::mangleFunctionParam(const ParmVarDecl *parm) { // get mangled if used as an rvalue of a known non-class type? assert(!parm->getType()->isArrayType() && "parameter's type is still an array type?"); - mangleQualifiers(parm->getType().getQualifiers()); + + if (const DependentAddressSpaceType *DAST = + dyn_cast<DependentAddressSpaceType>(parm->getType())) { + mangleQualifiers(DAST->getPointeeType().getQualifiers(), DAST); + } else { + mangleQualifiers(parm->getType().getQualifiers()); + } // Parameter index. if (parmIndex != 0) { diff --git a/lib/AST/Linkage.h b/lib/AST/Linkage.h new file mode 100644 index 000000000000..e6489c7ef2b3 --- /dev/null +++ b/lib/AST/Linkage.h @@ -0,0 +1,159 @@ +//===----- Linkage.h - Linkage calculation-related utilities ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides AST-internal utilities for linkage and visibility +// calculation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_AST_LINKAGE_H +#define LLVM_CLANG_LIB_AST_LINKAGE_H + +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/Type.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" + +namespace clang { +/// Kinds of LV computation. The linkage side of the computation is +/// always the same, but different things can change how visibility is +/// computed. +struct LVComputationKind { + /// The kind of entity whose visibility is ultimately being computed; + /// visibility computations for types and non-types follow different rules. + unsigned ExplicitKind : 1; + /// Whether explicit visibility attributes should be ignored. When set, + /// visibility may only be restricted by the visibility of template arguments. + unsigned IgnoreExplicitVisibility : 1; + /// Whether all visibility should be ignored. When set, we're only interested + /// in computing linkage. + unsigned IgnoreAllVisibility : 1; + + explicit LVComputationKind(NamedDecl::ExplicitVisibilityKind EK) + : ExplicitKind(EK), IgnoreExplicitVisibility(false), + IgnoreAllVisibility(false) {} + + NamedDecl::ExplicitVisibilityKind getExplicitVisibilityKind() const { + return static_cast<NamedDecl::ExplicitVisibilityKind>(ExplicitKind); + } + + bool isTypeVisibility() const { + return getExplicitVisibilityKind() == NamedDecl::VisibilityForType; + } + bool isValueVisibility() const { + return getExplicitVisibilityKind() == NamedDecl::VisibilityForValue; + } + + /// Do an LV computation when we only care about the linkage. + static LVComputationKind forLinkageOnly() { + LVComputationKind Result(NamedDecl::VisibilityForValue); + Result.IgnoreExplicitVisibility = true; + Result.IgnoreAllVisibility = true; + return Result; + } + + unsigned toBits() { + unsigned Bits = 0; + Bits = (Bits << 1) | ExplicitKind; + Bits = (Bits << 1) | IgnoreExplicitVisibility; + Bits = (Bits << 1) | IgnoreAllVisibility; + return Bits; + } +}; + +class LinkageComputer { + // We have a cache for repeated linkage/visibility computations. This saves us + // from exponential behavior in heavily templated code, such as: + // + // template <typename T, typename V> struct {}; + // using A = int; + // using B = Foo<A, A>; + // using C = Foo<B, B>; + // using D = Foo<C, C>; + // + // The unsigned represents an LVComputationKind. + using QueryType = std::pair<const NamedDecl *, unsigned>; + llvm::SmallDenseMap<QueryType, LinkageInfo, 8> CachedLinkageInfo; + + static QueryType makeCacheKey(const NamedDecl *ND, LVComputationKind Kind) { + return std::make_pair(ND, Kind.toBits()); + } + + llvm::Optional<LinkageInfo> lookup(const NamedDecl *ND, + LVComputationKind Kind) const { + auto Iter = CachedLinkageInfo.find(makeCacheKey(ND, Kind)); + if (Iter == CachedLinkageInfo.end()) + return None; + return Iter->second; + } + + void cache(const NamedDecl *ND, LVComputationKind Kind, LinkageInfo Info) { + CachedLinkageInfo[makeCacheKey(ND, Kind)] = Info; + } + + LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args, + LVComputationKind computation); + + LinkageInfo getLVForTemplateArgumentList(const TemplateArgumentList &TArgs, + LVComputationKind computation); + + void mergeTemplateLV(LinkageInfo &LV, const FunctionDecl *fn, + const FunctionTemplateSpecializationInfo *specInfo, + LVComputationKind computation); + + void mergeTemplateLV(LinkageInfo &LV, + const ClassTemplateSpecializationDecl *spec, + LVComputationKind computation); + + void mergeTemplateLV(LinkageInfo &LV, + const VarTemplateSpecializationDecl *spec, + LVComputationKind computation); + + LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, + LVComputationKind computation, + bool IgnoreVarTypeLinkage); + + LinkageInfo getLVForClassMember(const NamedDecl *D, + LVComputationKind computation, + bool IgnoreVarTypeLinkage); + + LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl, + LVComputationKind computation); + + LinkageInfo getLVForLocalDecl(const NamedDecl *D, + LVComputationKind computation); + + LinkageInfo getLVForType(const Type &T, LVComputationKind computation); + + LinkageInfo getLVForTemplateParameterList(const TemplateParameterList *Params, + LVComputationKind computation); + +public: + LinkageInfo computeLVForDecl(const NamedDecl *D, + LVComputationKind computation, + bool IgnoreVarTypeLinkage = false); + + LinkageInfo getLVForDecl(const NamedDecl *D, LVComputationKind computation); + + LinkageInfo computeTypeLinkageInfo(const Type *T); + LinkageInfo computeTypeLinkageInfo(QualType T) { + return computeTypeLinkageInfo(T.getTypePtr()); + } + + LinkageInfo getDeclLinkageAndVisibility(const NamedDecl *D); + + LinkageInfo getTypeLinkageAndVisibility(const Type *T); + LinkageInfo getTypeLinkageAndVisibility(QualType T) { + return getTypeLinkageAndVisibility(T.getTypePtr()); + } +}; +} // namespace clang + +#endif diff --git a/lib/AST/Mangle.cpp b/lib/AST/Mangle.cpp index 00d50c0e3bdf..56a2500274a7 100644 --- a/lib/AST/Mangle.cpp +++ b/lib/AST/Mangle.cpp @@ -103,6 +103,11 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl *D) { if (CC != CCM_Other) return true; + // If the declaration has an owning module for linkage purposes that needs to + // be mangled, we must mangle its name. + if (!D->hasExternalFormalLinkage() && D->getOwningModuleForLinkage()) + return true; + // In C, functions with no attributes never need to be mangled. Fastpath them. if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs()) return false; diff --git a/lib/AST/MicrosoftCXXABI.cpp b/lib/AST/MicrosoftCXXABI.cpp index 73324e40f3b1..b19491f31304 100644 --- a/lib/AST/MicrosoftCXXABI.cpp +++ b/lib/AST/MicrosoftCXXABI.cpp @@ -76,8 +76,8 @@ class MicrosoftCXXABI : public CXXABI { public: MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { } - std::pair<uint64_t, unsigned> - getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const override; + MemberPointerInfo + getMemberPointerInfo(const MemberPointerType *MPT) const override; CallingConv getDefaultMethodCallConv(bool isVariadic) const override { if (!isVariadic && @@ -227,7 +227,7 @@ getMSMemberPointerSlots(const MemberPointerType *MPT) { return std::make_pair(Ptrs, Ints); } -std::pair<uint64_t, unsigned> MicrosoftCXXABI::getMemberPointerWidthAndAlign( +CXXABI::MemberPointerInfo MicrosoftCXXABI::getMemberPointerInfo( const MemberPointerType *MPT) const { // The nominal struct is laid out with pointers followed by ints and aligned // to a pointer width if any are present and an int width otherwise. @@ -237,22 +237,25 @@ std::pair<uint64_t, unsigned> MicrosoftCXXABI::getMemberPointerWidthAndAlign( unsigned Ptrs, Ints; std::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT); - uint64_t Width = Ptrs * PtrSize + Ints * IntSize; - unsigned Align; + MemberPointerInfo MPI; + MPI.HasPadding = false; + MPI.Width = Ptrs * PtrSize + Ints * IntSize; // When MSVC does x86_32 record layout, it aligns aggregate member pointers to // 8 bytes. However, __alignof usually returns 4 for data memptrs and 8 for // function memptrs. if (Ptrs + Ints > 1 && Target.getTriple().isArch32Bit()) - Align = 64; + MPI.Align = 64; else if (Ptrs) - Align = Target.getPointerAlign(0); + MPI.Align = Target.getPointerAlign(0); else - Align = Target.getIntAlign(); + MPI.Align = Target.getIntAlign(); - if (Target.getTriple().isArch64Bit()) - Width = llvm::alignTo(Width, Align); - return std::make_pair(Width, Align); + if (Target.getTriple().isArch64Bit()) { + MPI.Width = llvm::alignTo(MPI.Width, MPI.Align); + MPI.HasPadding = MPI.Width != (Ptrs * PtrSize + Ints * IntSize); + } + return MPI; } CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) { diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 24b16f892e7a..0c55c1a92287 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -1192,6 +1192,15 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, // <operator-name> ::= ?__L # co_await case OO_Coawait: Out << "?__L"; break; + case OO_Spaceship: { + // FIXME: Once MS picks a mangling, use it. + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this three-way comparison operator yet"); + Diags.Report(Loc, DiagID); + break; + } + case OO_Conditional: { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, @@ -1866,6 +1875,7 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, Out << "$$T"; break; + case BuiltinType::Float16: case BuiltinType::Float128: case BuiltinType::Half: { DiagnosticsEngine &Diags = Context.getDiags(); @@ -2324,13 +2334,15 @@ void MicrosoftCXXNameMangler::mangleType(const PointerType *T, Qualifiers Quals, manglePointerExtQualifiers(Quals, PointeeType); mangleType(PointeeType, Range); } + void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T, Qualifiers Quals, SourceRange Range) { + if (T->isObjCIdType() || T->isObjCClassType()) + return mangleType(T->getPointeeType(), Range, QMM_Drop); + QualType PointeeType = T->getPointeeType(); manglePointerCVQualifiers(Quals); manglePointerExtQualifiers(Quals, PointeeType); - // Object pointers never have qualifiers. - Out << 'A'; mangleType(PointeeType, Range); } @@ -2427,6 +2439,15 @@ void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T, << Range; } +void MicrosoftCXXNameMangler::mangleType(const DependentAddressSpaceType *T, + Qualifiers, SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Error, + "cannot mangle this dependent address space type yet"); + Diags.Report(Range.getBegin(), DiagID) << Range; +} + void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, Qualifiers, SourceRange) { // ObjC interfaces have structs underlying them. @@ -2438,7 +2459,7 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, Qualifiers, SourceRange Range) { // We don't allow overloading by different protocol qualification, // so mangling them isn't necessary. - mangleType(T->getBaseType(), Range); + mangleType(T->getBaseType(), Range, QMM_Drop); } void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T, diff --git a/lib/AST/NSAPI.cpp b/lib/AST/NSAPI.cpp index e7c8c16b0145..8adaef1fb640 100644 --- a/lib/AST/NSAPI.cpp +++ b/lib/AST/NSAPI.cpp @@ -441,6 +441,7 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const { case BuiltinType::Int128: case BuiltinType::LongDouble: case BuiltinType::UInt128: + case BuiltinType::Float16: case BuiltinType::Float128: case BuiltinType::NullPtr: case BuiltinType::ObjCClass: diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp index e2e0dbeec0dd..889f8308a93c 100644 --- a/lib/AST/NestedNameSpecifier.cpp +++ b/lib/AST/NestedNameSpecifier.cpp @@ -1,4 +1,4 @@ -//===--- NestedNameSpecifier.cpp - C++ nested name specifiers -----*- C++ -*-=// +//===- NestedNameSpecifier.cpp - C++ nested name specifiers ---------------===// // // The LLVM Compiler Infrastructure // @@ -11,16 +11,28 @@ // a C++ nested-name-specifier. // //===----------------------------------------------------------------------===// + #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/PrettyPrinter.h" +#include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" -#include "llvm/Support/AlignOf.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> #include <cassert> +#include <cstdlib> +#include <cstring> using namespace clang; @@ -314,8 +326,8 @@ NestedNameSpecifier::print(raw_ostream &OS, SpecType->getTemplateName().print(OS, InnerPolicy, true); // Print the template argument list. - TemplateSpecializationType::PrintTemplateArgumentList( - OS, SpecType->template_arguments(), InnerPolicy); + printTemplateArgumentList(OS, SpecType->template_arguments(), + InnerPolicy); } else { // Print the type normally QualType(T, 0).print(OS, InnerPolicy); @@ -375,22 +387,20 @@ NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) { return Length; } -namespace { - /// \brief Load a (possibly unaligned) source location from a given address - /// and offset. - SourceLocation LoadSourceLocation(void *Data, unsigned Offset) { - unsigned Raw; - memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned)); - return SourceLocation::getFromRawEncoding(Raw); - } +/// \brief Load a (possibly unaligned) source location from a given address +/// and offset. +static SourceLocation LoadSourceLocation(void *Data, unsigned Offset) { + unsigned Raw; + memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned)); + return SourceLocation::getFromRawEncoding(Raw); +} - /// \brief Load a (possibly unaligned) pointer from a given address and - /// offset. - void *LoadPointer(void *Data, unsigned Offset) { - void *Result; - memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*)); - return Result; - } +/// \brief Load a (possibly unaligned) pointer from a given address and +/// offset. +static void *LoadPointer(void *Data, unsigned Offset) { + void *Result; + memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*)); + return Result; } SourceRange NestedNameSpecifierLoc::getSourceRange() const { @@ -446,53 +456,49 @@ TypeLoc NestedNameSpecifierLoc::getTypeLoc() const { return TypeLoc(Qualifier->getAsType(), TypeData); } -namespace { - void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, +static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, unsigned &BufferCapacity) { - if (Start == End) - return; + if (Start == End) + return; - if (BufferSize + (End - Start) > BufferCapacity) { - // Reallocate the buffer. - unsigned NewCapacity = std::max( - (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2), - (unsigned)(BufferSize + (End - Start))); - char *NewBuffer = static_cast<char *>(malloc(NewCapacity)); - if (BufferCapacity) { - memcpy(NewBuffer, Buffer, BufferSize); - free(Buffer); - } - Buffer = NewBuffer; - BufferCapacity = NewCapacity; + if (BufferSize + (End - Start) > BufferCapacity) { + // Reallocate the buffer. + unsigned NewCapacity = std::max( + (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2), + (unsigned)(BufferSize + (End - Start))); + char *NewBuffer = static_cast<char *>(malloc(NewCapacity)); + if (BufferCapacity) { + memcpy(NewBuffer, Buffer, BufferSize); + free(Buffer); } - - memcpy(Buffer + BufferSize, Start, End - Start); - BufferSize += End-Start; + Buffer = NewBuffer; + BufferCapacity = NewCapacity; } + + memcpy(Buffer + BufferSize, Start, End - Start); + BufferSize += End-Start; +} - /// \brief Save a source location to the given buffer. - void SaveSourceLocation(SourceLocation Loc, char *&Buffer, - unsigned &BufferSize, unsigned &BufferCapacity) { - unsigned Raw = Loc.getRawEncoding(); - Append(reinterpret_cast<char *>(&Raw), - reinterpret_cast<char *>(&Raw) + sizeof(unsigned), - Buffer, BufferSize, BufferCapacity); - } +/// \brief Save a source location to the given buffer. +static void SaveSourceLocation(SourceLocation Loc, char *&Buffer, + unsigned &BufferSize, unsigned &BufferCapacity) { + unsigned Raw = Loc.getRawEncoding(); + Append(reinterpret_cast<char *>(&Raw), + reinterpret_cast<char *>(&Raw) + sizeof(unsigned), + Buffer, BufferSize, BufferCapacity); +} - /// \brief Save a pointer to the given buffer. - void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize, - unsigned &BufferCapacity) { - Append(reinterpret_cast<char *>(&Ptr), - reinterpret_cast<char *>(&Ptr) + sizeof(void *), - Buffer, BufferSize, BufferCapacity); - } +/// \brief Save a pointer to the given buffer. +static void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize, + unsigned &BufferCapacity) { + Append(reinterpret_cast<char *>(&Ptr), + reinterpret_cast<char *>(&Ptr) + sizeof(void *), + Buffer, BufferSize, BufferCapacity); } NestedNameSpecifierLocBuilder:: NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other) - : Representation(Other.Representation), Buffer(nullptr), - BufferSize(0), BufferCapacity(0) -{ + : Representation(Other.Representation) { if (!Other.Buffer) return; diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp index 121724a73152..17c95f2a0af7 100644 --- a/lib/AST/ODRHash.cpp +++ b/lib/AST/ODRHash.cpp @@ -158,7 +158,14 @@ void ODRHash::AddTemplateArgument(TemplateArgument TA) { } } -void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) {} +void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) { + assert(TPL && "Expecting non-null pointer."); + + ID.AddInteger(TPL->size()); + for (auto *ND : TPL->asArray()) { + AddSubDecl(ND); + } +} void ODRHash::clear() { DeclMap.clear(); @@ -199,6 +206,7 @@ unsigned ODRHash::CalculateHash() { return ID.ComputeHash(); } +namespace { // 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> { @@ -235,6 +243,10 @@ public: } } + void AddTemplateArgument(TemplateArgument TA) { + Hash.AddTemplateArgument(TA); + } + void Visit(const Decl *D) { ID.AddInteger(D->getKind()); Inherited::Visit(D); @@ -342,7 +354,44 @@ public: AddDecl(D->getFriendDecl()); } } + + void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { + // Only care about default arguments as part of the definition. + const bool hasDefaultArgument = + D->hasDefaultArgument() && !D->defaultArgumentWasInherited(); + Hash.AddBoolean(hasDefaultArgument); + if (hasDefaultArgument) { + AddTemplateArgument(D->getDefaultArgument()); + } + + Inherited::VisitTemplateTypeParmDecl(D); + } + + void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) { + // Only care about default arguments as part of the definition. + const bool hasDefaultArgument = + D->hasDefaultArgument() && !D->defaultArgumentWasInherited(); + Hash.AddBoolean(hasDefaultArgument); + if (hasDefaultArgument) { + AddStmt(D->getDefaultArgument()); + } + + Inherited::VisitNonTypeTemplateParmDecl(D); + } + + void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D) { + // Only care about default arguments as part of the definition. + const bool hasDefaultArgument = + D->hasDefaultArgument() && !D->defaultArgumentWasInherited(); + Hash.AddBoolean(hasDefaultArgument); + if (hasDefaultArgument) { + AddTemplateArgument(D->getDefaultArgument().getArgument()); + } + + Inherited::VisitTemplateTemplateParmDecl(D); + } }; +} // namespace // Only allow a small portion of Decl's to be processed. Remove this once // all Decl's can be handled. @@ -401,6 +450,20 @@ void ODRHash::AddCXXRecordDecl(const CXXRecordDecl *Record) { for (auto SubDecl : Decls) { AddSubDecl(SubDecl); } + + const ClassTemplateDecl *TD = Record->getDescribedClassTemplate(); + AddBoolean(TD); + if (TD) { + AddTemplateParameterList(TD->getTemplateParameters()); + } + + ID.AddInteger(Record->getNumBases()); + auto Bases = Record->bases(); + for (auto Base : Bases) { + AddQualType(Base.getType()); + ID.AddInteger(Base.isVirtual()); + ID.AddInteger(Base.getAccessSpecifierAsWritten()); + } } void ODRHash::AddDecl(const Decl *D) { @@ -420,6 +483,7 @@ void ODRHash::AddDecl(const Decl *D) { } } +namespace { // 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> { @@ -608,6 +672,7 @@ public: AddDecl(T->getDecl()); } }; +} // namespace void ODRHash::AddType(const Type *T) { assert(T && "Expecting non-null pointer."); diff --git a/lib/AST/OpenMPClause.cpp b/lib/AST/OpenMPClause.cpp index 2c4d159a1bc8..4feac0cfd041 100644 --- a/lib/AST/OpenMPClause.cpp +++ b/lib/AST/OpenMPClause.cpp @@ -1,4 +1,4 @@ -//===--- OpenMPClause.cpp - Classes for OpenMP clauses --------------------===// +//===- OpenMPClause.cpp - Classes for OpenMP clauses ----------------------===// // // The LLVM Compiler Infrastructure // @@ -12,8 +12,14 @@ //===----------------------------------------------------------------------===// #include "clang/AST/OpenMPClause.h" - #include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include <algorithm> +#include <cassert> using namespace clang; @@ -48,6 +54,8 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { return static_cast<const OMPReductionClause *>(C); case OMPC_task_reduction: return static_cast<const OMPTaskReductionClause *>(C); + case OMPC_in_reduction: + return static_cast<const OMPInReductionClause *>(C); case OMPC_linear: return static_cast<const OMPLinearClause *>(C); case OMPC_if: @@ -58,6 +66,8 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { return static_cast<const OMPNumTeamsClause *>(C); case OMPC_thread_limit: return static_cast<const OMPThreadLimitClause *>(C); + case OMPC_device: + return static_cast<const OMPDeviceClause *>(C); case OMPC_default: case OMPC_proc_bind: case OMPC_final: @@ -81,7 +91,6 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { case OMPC_capture: case OMPC_seq_cst: case OMPC_depend: - case OMPC_device: case OMPC_threads: case OMPC_simd: case OMPC_map: @@ -116,6 +125,8 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) return static_cast<const OMPReductionClause *>(C); case OMPC_task_reduction: return static_cast<const OMPTaskReductionClause *>(C); + case OMPC_in_reduction: + return static_cast<const OMPInReductionClause *>(C); case OMPC_linear: return static_cast<const OMPLinearClause *>(C); case OMPC_schedule: @@ -562,6 +573,69 @@ OMPTaskReductionClause *OMPTaskReductionClause::CreateEmpty(const ASTContext &C, return new (Mem) OMPTaskReductionClause(N); } +void OMPInReductionClause::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 OMPInReductionClause::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 OMPInReductionClause::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 OMPInReductionClause::setReductionOps(ArrayRef<Expr *> ReductionOps) { + assert(ReductionOps.size() == varlist_size() && "Number of in reduction " + "expressions is not the same " + "as the preallocated buffer"); + std::copy(ReductionOps.begin(), ReductionOps.end(), getRHSExprs().end()); +} + +void OMPInReductionClause::setTaskgroupDescriptors( + ArrayRef<Expr *> TaskgroupDescriptors) { + assert(TaskgroupDescriptors.size() == varlist_size() && + "Number of in reduction descriptors is not the same as the " + "preallocated buffer"); + std::copy(TaskgroupDescriptors.begin(), TaskgroupDescriptors.end(), + getReductionOps().end()); +} + +OMPInReductionClause *OMPInReductionClause::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, + ArrayRef<Expr *> TaskgroupDescriptors, Stmt *PreInit, Expr *PostUpdate) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(6 * VL.size())); + OMPInReductionClause *Clause = new (Mem) OMPInReductionClause( + StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo); + Clause->setVarRefs(VL); + Clause->setPrivates(Privates); + Clause->setLHSExprs(LHSExprs); + Clause->setRHSExprs(RHSExprs); + Clause->setReductionOps(ReductionOps); + Clause->setTaskgroupDescriptors(TaskgroupDescriptors); + Clause->setPreInitStmt(PreInit); + Clause->setPostUpdateExpr(PostUpdate); + return Clause; +} + +OMPInReductionClause *OMPInReductionClause::CreateEmpty(const ASTContext &C, + unsigned N) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(6 * N)); + return new (Mem) OMPInReductionClause(N); +} + OMPFlushClause *OMPFlushClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, @@ -648,7 +722,6 @@ OMPMapClause::Create(const ASTContext &C, SourceLocation StartLoc, MappableExprComponentListsRef ComponentLists, OpenMPMapClauseKind TypeModifier, OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc) { - unsigned NumVars = Vars.size(); unsigned NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations); diff --git a/lib/Tooling/Core/QualTypeNames.cpp b/lib/AST/QualTypeNames.cpp index 721c2c92fc27..86c0eff9f78c 100644 --- a/lib/Tooling/Core/QualTypeNames.cpp +++ b/lib/AST/QualTypeNames.cpp @@ -9,11 +9,11 @@ // //===----------------------------------------------------------------------===// -#include "clang/Tooling/Core/QualTypeNames.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/GlobalDecl.h" #include "clang/AST/Mangle.h" +#include "clang/AST/QualTypeNames.h" #include <stdio.h> #include <memory> @@ -21,17 +21,6 @@ namespace clang { namespace TypeName { -/// \brief Generates a QualType that can be used to name the same type -/// if used at the end of the current translation unit. This ignores -/// issues such as type shadowing. -/// -/// \param[in] QT - the type for which the fully qualified type will be -/// returned. -/// \param[in] Ctx - the ASTContext to be used. -/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace -/// specifier "::" should be prepended or not. -static QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx, - bool WithGlobalNsPrefix); /// \brief Create a NestedNameSpecifier for Namesp and its enclosing /// scopes. diff --git a/lib/AST/RecordLayout.cpp b/lib/AST/RecordLayout.cpp index 299fd111bf6a..37fe029f53bd 100644 --- a/lib/AST/RecordLayout.cpp +++ b/lib/AST/RecordLayout.cpp @@ -1,4 +1,4 @@ -//===-- RecordLayout.cpp - Layout information for a struct/union -*- C++ -*-==// +//===- RecordLayout.cpp - Layout information for a struct/union -----------===// // // The LLVM Compiler Infrastructure // @@ -11,9 +11,11 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/ASTContext.h" #include "clang/AST/RecordLayout.h" +#include "clang/AST/ASTContext.h" +#include "clang/Basic/TargetCXXABI.h" #include "clang/Basic/TargetInfo.h" +#include <cassert> using namespace clang; @@ -32,7 +34,7 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits datasize, ArrayRef<uint64_t> fieldoffsets) : Size(size), DataSize(datasize), Alignment(alignment), - RequiredAlignment(requiredAlignment), CXXInfo(nullptr) { + RequiredAlignment(requiredAlignment) { FieldOffsets.append(Ctx, fieldoffsets.begin(), fieldoffsets.end()); } @@ -73,7 +75,6 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CXXInfo->EndsWithZeroSizedObject = EndsWithZeroSizedObject; CXXInfo->LeadsWithZeroSizedBase = LeadsWithZeroSizedBase; - #ifndef NDEBUG if (const CXXRecordDecl *PrimaryBase = getPrimaryBase()) { if (isPrimaryBaseVirtual()) { diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index c0b9cadca422..a9d43dfa80c5 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -632,6 +632,9 @@ protected: /// pointer, as opposed to inheriting one from a primary base class. bool HasOwnVFPtr; + /// \brief the flag of field offset changing due to packed attribute. + bool HasPackedField; + typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy; /// Bases - base classes and their offsets in the record. @@ -666,7 +669,7 @@ protected: NonVirtualSize(CharUnits::Zero()), NonVirtualAlignment(CharUnits::One()), PrimaryBase(nullptr), PrimaryBaseIsVirtual(false), HasOwnVFPtr(false), - FirstNearlyEmptyVBase(nullptr) {} + HasPackedField(false), FirstNearlyEmptyVBase(nullptr) {} void Layout(const RecordDecl *D); void Layout(const CXXRecordDecl *D); @@ -1166,7 +1169,6 @@ ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { // Query the external layout to see if it provides an offset. bool HasExternalLayout = false; if (UseExternalLayout) { - llvm::DenseMap<const CXXRecordDecl *, CharUnits>::iterator Known; if (Base->IsVirtual) HasExternalLayout = External.getExternalNVBaseOffset(Base->Class, Offset); else @@ -1729,7 +1731,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D, const ArrayType* ATy = Context.getAsArrayType(D->getType()); FieldAlign = Context.getTypeAlignInChars(ATy->getElementType()); } else if (const ReferenceType *RT = D->getType()->getAs<ReferenceType>()) { - unsigned AS = RT->getPointeeType().getAddressSpace(); + unsigned AS = Context.getTargetAddressSpace(RT->getPointeeType()); FieldSize = Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(AS)); FieldAlign = @@ -1847,7 +1849,6 @@ void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) { uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit; uint64_t UnpackedSizeInBits = llvm::alignTo(getSizeInBits(), Context.toBits(UnpackedAlignment)); - CharUnits UnpackedSize = Context.toCharUnitsFromBits(UnpackedSizeInBits); uint64_t RoundedSize = llvm::alignTo(getSizeInBits(), Context.toBits(Alignment)); @@ -1882,10 +1883,11 @@ void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) { << (InBits ? 1 : 0); // (byte|bit) } - // Warn if we packed it unnecessarily. If the alignment is 1 byte don't - // bother since there won't be alignment issues. - if (Packed && UnpackedAlignment > CharUnits::One() && - getSize() == UnpackedSize) + // Warn if we packed it unnecessarily, when the unpacked alignment is not + // greater than the one after packing, the size in bits doesn't change and + // the offset of each field is identical. + if (Packed && UnpackedAlignment <= Alignment && + UnpackedSizeInBits == getSizeInBits() && !HasPackedField) Diag(D->getLocation(), diag::warn_unnecessary_packed) << Context.getTypeDeclType(RD); } @@ -1977,13 +1979,10 @@ void ItaniumRecordLayoutBuilder::CheckFieldPadding( << Context.getTypeDeclType(D->getParent()) << PadSize << (InBits ? 1 : 0); // (byte|bit) - } - - // Warn if we packed it unnecessarily. If the alignment is 1 byte don't - // bother since there won't be alignment issues. - if (isPacked && UnpackedAlign > CharBitNum && Offset == UnpackedOffset) - Diag(D->getLocation(), diag::warn_unnecessary_packed) - << D->getIdentifier(); + } + if (isPacked && Offset != UnpackedOffset) { + HasPackedField = true; + } } static const CXXMethodDecl *computeKeyFunction(ASTContext &Context, @@ -2084,7 +2083,7 @@ static bool mustSkipTailPadding(TargetCXXABI ABI, const CXXRecordDecl *RD) { // rules, we should implement the restrictions about over-sized // bitfields: // - // http://mentorembedded.github.com/cxx-abi/abi.html#POD : + // http://itanium-cxx-abi.github.io/cxx-abi/abi.html#POD : // In general, a type is considered a POD for the purposes of // layout if it is a POD type (in the sense of ISO C++ // [basic.types]). However, a POD-struct or POD-union (in the @@ -2896,13 +2895,12 @@ void MicrosoftRecordLayoutBuilder::computeVtorDispSet( Work.insert(MD); while (!Work.empty()) { const CXXMethodDecl *MD = *Work.begin(); - CXXMethodDecl::method_iterator i = MD->begin_overridden_methods(), - e = MD->end_overridden_methods(); + auto MethodRange = MD->overridden_methods(); // If a virtual method has no-overrides it lives in its parent's vtable. - if (i == e) + if (MethodRange.begin() == MethodRange.end()) BasesWithOverriddenMethods.insert(MD->getParent()); else - Work.insert(i, e); + Work.insert(MethodRange.begin(), MethodRange.end()); // We've finished processing this element, remove it from the working set. Work.erase(MD); } diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 2367cadf645c..8d240c1336ab 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -1,4 +1,4 @@ -//===--- Stmt.cpp - Statement AST Node Implementation ---------------------===// +//===- Stmt.cpp - Statement AST Node Implementation -----------------------===// // // The LLVM Compiler Infrastructure // @@ -13,6 +13,8 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclGroup.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" @@ -22,10 +24,24 @@ #include "clang/AST/StmtOpenMP.h" #include "clang/AST/Type.h" #include "clang/Basic/CharInfo.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Token.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cstring> +#include <string> +#include <utility> + using namespace clang; static struct StmtClassNameTable { @@ -150,6 +166,7 @@ const Stmt *Stmt::stripLabelLikeStatements() const { } namespace { + struct good {}; struct bad {}; @@ -191,7 +208,8 @@ namespace { (void) is_good(implements_getLocStart(&type::getLocStart)) #define ASSERT_IMPLEMENTS_getLocEnd(type) \ (void) is_good(implements_getLocEnd(&type::getLocEnd)) -} + +} // namespace /// Check whether the various Stmt classes implement their member /// functions. @@ -222,6 +240,7 @@ Stmt::child_range Stmt::children() { // // See also Expr.cpp:getExprLoc(). namespace { + /// This implementation is used when a class provides a custom /// implementation of getSourceRange. template <class S, class T> @@ -240,7 +259,8 @@ namespace { return SourceRange(static_cast<const S*>(stmt)->getLocStart(), static_cast<const S*>(stmt)->getLocEnd()); } -} + +} // namespace SourceRange Stmt::getSourceRange() const { switch (getStmtClass()) { @@ -286,7 +306,7 @@ CompoundStmt::CompoundStmt(const ASTContext &C, ArrayRef<Stmt*> Stmts, assert(CompoundStmtBits.NumStmts == Stmts.size() && "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!"); - if (Stmts.size() == 0) { + if (Stmts.empty()) { Body = nullptr; return; } @@ -408,6 +428,7 @@ StringRef GCCAsmStmt::getOutputConstraint(unsigned i) const { Expr *GCCAsmStmt::getInputExpr(unsigned i) { return cast<Expr>(Exprs[i + NumOutputs]); } + void GCCAsmStmt::setInputExpr(unsigned i, Expr *E) { Exprs[i + NumOutputs] = E; } @@ -506,7 +527,7 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces, unsigned LastAsmStringToken = 0; unsigned LastAsmStringOffset = 0; - while (1) { + while (true) { // Done with the string? if (CurPtr == StrEnd) { if (!CurStringPiece.empty()) @@ -682,6 +703,7 @@ Expr *MSAsmStmt::getOutputExpr(unsigned i) { Expr *MSAsmStmt::getInputExpr(unsigned i) { return cast<Expr>(Exprs[i + NumOutputs]); } + void MSAsmStmt::setInputExpr(unsigned i, Expr *E) { Exprs[i + NumOutputs] = E; } @@ -696,9 +718,8 @@ GCCAsmStmt::GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, StringLiteral **constraints, Expr **exprs, StringLiteral *asmstr, unsigned numclobbers, StringLiteral **clobbers, SourceLocation rparenloc) - : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs, - numinputs, numclobbers), RParenLoc(rparenloc), AsmStr(asmstr) { - + : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs, + numinputs, numclobbers), RParenLoc(rparenloc), AsmStr(asmstr) { unsigned NumExprs = NumOutputs + NumInputs; Names = new (C) IdentifierInfo*[NumExprs]; @@ -721,10 +742,9 @@ MSAsmStmt::MSAsmStmt(const ASTContext &C, SourceLocation asmloc, ArrayRef<StringRef> constraints, ArrayRef<Expr*> exprs, StringRef asmstr, ArrayRef<StringRef> clobbers, SourceLocation endloc) - : AsmStmt(MSAsmStmtClass, asmloc, issimple, isvolatile, numoutputs, - numinputs, clobbers.size()), LBraceLoc(lbraceloc), - EndLoc(endloc), NumAsmToks(asmtoks.size()) { - + : AsmStmt(MSAsmStmtClass, asmloc, issimple, isvolatile, numoutputs, + numinputs, clobbers.size()), LBraceLoc(lbraceloc), + EndLoc(endloc), NumAsmToks(asmtoks.size()) { initialize(C, asmstr, asmtoks, constraints, exprs, clobbers); } @@ -909,14 +929,9 @@ Expr* ReturnStmt::getRetValue() { return cast_or_null<Expr>(RetExpr); } -SEHTryStmt::SEHTryStmt(bool IsCXXTry, - SourceLocation TryLoc, - Stmt *TryBlock, +SEHTryStmt::SEHTryStmt(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock, Stmt *Handler) - : Stmt(SEHTryStmtClass), - IsCXXTry(IsCXXTry), - TryLoc(TryLoc) -{ + : Stmt(SEHTryStmtClass), IsCXXTry(IsCXXTry), TryLoc(TryLoc) { Children[TRY] = TryBlock; Children[HANDLER] = Handler; } @@ -935,12 +950,8 @@ SEHFinallyStmt* SEHTryStmt::getFinallyHandler() const { return dyn_cast<SEHFinallyStmt>(getHandler()); } -SEHExceptStmt::SEHExceptStmt(SourceLocation Loc, - Expr *FilterExpr, - Stmt *Block) - : Stmt(SEHExceptStmtClass), - Loc(Loc) -{ +SEHExceptStmt::SEHExceptStmt(SourceLocation Loc, Expr *FilterExpr, Stmt *Block) + : Stmt(SEHExceptStmtClass), Loc(Loc) { Children[FILTER_EXPR] = FilterExpr; Children[BLOCK] = Block; } @@ -950,12 +961,8 @@ SEHExceptStmt* SEHExceptStmt::Create(const ASTContext &C, SourceLocation Loc, return new(C) SEHExceptStmt(Loc,FilterExpr,Block); } -SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc, - Stmt *Block) - : Stmt(SEHFinallyStmtClass), - Loc(Loc), - Block(Block) -{} +SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc, Stmt *Block) + : Stmt(SEHFinallyStmtClass), Loc(Loc), Block(Block) {} SEHFinallyStmt* SEHFinallyStmt::Create(const ASTContext &C, SourceLocation Loc, Stmt *Block) { @@ -1037,7 +1044,7 @@ CapturedStmt::CapturedStmt(Stmt *S, CapturedRegionKind Kind, CapturedStmt::CapturedStmt(EmptyShell Empty, unsigned NumCaptures) : Stmt(CapturedStmtClass, Empty), NumCaptures(NumCaptures), - CapDeclAndKind(nullptr, CR_Default), TheRecordDecl(nullptr) { + CapDeclAndKind(nullptr, CR_Default) { getStoredStmts()[NumCaptures] = nullptr; } @@ -1090,6 +1097,7 @@ Stmt::child_range CapturedStmt::children() { CapturedDecl *CapturedStmt::getCapturedDecl() { return CapDeclAndKind.getPointer(); } + const CapturedDecl *CapturedStmt::getCapturedDecl() const { return CapDeclAndKind.getPointer(); } @@ -1114,11 +1122,7 @@ bool CapturedStmt::capturesVariable(const VarDecl *Var) const { for (const auto &I : captures()) { if (!I.capturesVariable() && !I.capturesVariableByCopy()) continue; - - // This does not handle variable redeclarations. This should be - // extended to capture variables with redeclarations, for example - // a thread-private variable in OpenMP. - if (I.getCapturedVar() == Var) + if (I.getCapturedVar()->getCanonicalDecl() == Var->getCanonicalDecl()) return true; } diff --git a/lib/AST/StmtIterator.cpp b/lib/AST/StmtIterator.cpp index 861d0908209d..00056e83af2c 100644 --- a/lib/AST/StmtIterator.cpp +++ b/lib/AST/StmtIterator.cpp @@ -1,4 +1,4 @@ -//===--- StmtIterator.cpp - Iterators for Statements ------------------------===// +//===- StmtIterator.cpp - Iterators for Statements ------------------------===// // // The LLVM Compiler Infrastructure // @@ -13,6 +13,11 @@ #include "clang/AST/StmtIterator.h" #include "clang/AST/Decl.h" +#include "clang/AST/Type.h" +#include "clang/Basic/LLVM.h" +#include "llvm/Support/Casting.h" +#include <cassert> +#include <cstdint> using namespace clang; @@ -31,7 +36,7 @@ static inline const VariableArrayType *FindVA(const Type* t) { } void StmtIteratorBase::NextVA() { - assert (getVAPtr()); + assert(getVAPtr()); const VariableArrayType *p = getVAPtr(); p = FindVA(p->getElementType().getTypePtr()); @@ -93,22 +98,22 @@ bool StmtIteratorBase::HandleDecl(Decl* D) { } StmtIteratorBase::StmtIteratorBase(Decl** dgi, Decl** dge) - : DGI(dgi), RawVAPtr(DeclGroupMode), DGE(dge) { + : DGI(dgi), RawVAPtr(DeclGroupMode), DGE(dge) { NextDecl(false); } StmtIteratorBase::StmtIteratorBase(const VariableArrayType* t) - : DGI(nullptr), RawVAPtr(SizeOfTypeVAMode) { + : DGI(nullptr), RawVAPtr(SizeOfTypeVAMode) { RawVAPtr |= reinterpret_cast<uintptr_t>(t); } Stmt*& StmtIteratorBase::GetDeclExpr() const { if (const VariableArrayType* VAPtr = getVAPtr()) { - assert (VAPtr->SizeExpr); + assert(VAPtr->SizeExpr); return const_cast<Stmt*&>(VAPtr->SizeExpr); } - assert (inDeclGroup()); + assert(inDeclGroup()); VarDecl* VD = cast<VarDecl>(*DGI); return *VD->getInitAddress(); } diff --git a/lib/AST/StmtOpenMP.cpp b/lib/AST/StmtOpenMP.cpp index 1dcb4fd5196b..87bf5aaaa585 100644 --- a/lib/AST/StmtOpenMP.cpp +++ b/lib/AST/StmtOpenMP.cpp @@ -524,14 +524,15 @@ OMPTaskwaitDirective *OMPTaskwaitDirective::CreateEmpty(const ASTContext &C, OMPTaskgroupDirective *OMPTaskgroupDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *ReductionRef) { unsigned Size = llvm::alignTo(sizeof(OMPTaskgroupDirective) + sizeof(OMPClause *) * Clauses.size(), alignof(Stmt *)); - void *Mem = C.Allocate(Size + sizeof(Stmt *)); + void *Mem = C.Allocate(Size + sizeof(Stmt *) + sizeof(Expr *)); OMPTaskgroupDirective *Dir = new (Mem) OMPTaskgroupDirective(StartLoc, EndLoc, Clauses.size()); Dir->setAssociatedStmt(AssociatedStmt); + Dir->setReductionRef(ReductionRef); Dir->setClauses(Clauses); return Dir; } @@ -542,7 +543,7 @@ OMPTaskgroupDirective *OMPTaskgroupDirective::CreateEmpty(const ASTContext &C, unsigned Size = llvm::alignTo(sizeof(OMPTaskgroupDirective) + sizeof(OMPClause *) * NumClauses, alignof(Stmt *)); - void *Mem = C.Allocate(Size + sizeof(Stmt *)); + void *Mem = C.Allocate(Size + sizeof(Stmt *) + sizeof(Expr *)); return new (Mem) OMPTaskgroupDirective(NumClauses); } @@ -794,13 +795,14 @@ OMPTargetDataDirective *OMPTargetDataDirective::CreateEmpty(const ASTContext &C, OMPTargetEnterDataDirective *OMPTargetEnterDataDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses) { + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { void *Mem = C.Allocate( llvm::alignTo(sizeof(OMPTargetEnterDataDirective), alignof(OMPClause *)) + - sizeof(OMPClause *) * Clauses.size()); + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPTargetEnterDataDirective *Dir = new (Mem) OMPTargetEnterDataDirective(StartLoc, EndLoc, Clauses.size()); Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); return Dir; } @@ -809,20 +811,20 @@ OMPTargetEnterDataDirective::CreateEmpty(const ASTContext &C, unsigned N, EmptyShell) { void *Mem = C.Allocate( llvm::alignTo(sizeof(OMPTargetEnterDataDirective), alignof(OMPClause *)) + - sizeof(OMPClause *) * N); + sizeof(OMPClause *) * N + sizeof(Stmt *)); return new (Mem) OMPTargetEnterDataDirective(N); } -OMPTargetExitDataDirective * -OMPTargetExitDataDirective::Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses) { +OMPTargetExitDataDirective *OMPTargetExitDataDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { void *Mem = C.Allocate( llvm::alignTo(sizeof(OMPTargetExitDataDirective), alignof(OMPClause *)) + - sizeof(OMPClause *) * Clauses.size()); + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPTargetExitDataDirective *Dir = new (Mem) OMPTargetExitDataDirective(StartLoc, EndLoc, Clauses.size()); Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); return Dir; } @@ -831,7 +833,7 @@ OMPTargetExitDataDirective::CreateEmpty(const ASTContext &C, unsigned N, EmptyShell) { void *Mem = C.Allocate( llvm::alignTo(sizeof(OMPTargetExitDataDirective), alignof(OMPClause *)) + - sizeof(OMPClause *) * N); + sizeof(OMPClause *) * N + sizeof(Stmt *)); return new (Mem) OMPTargetExitDataDirective(N); } @@ -1006,16 +1008,17 @@ OMPDistributeDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, return new (Mem) OMPDistributeDirective(CollapsedNum, NumClauses); } -OMPTargetUpdateDirective * -OMPTargetUpdateDirective::Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses) { +OMPTargetUpdateDirective *OMPTargetUpdateDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { unsigned Size = llvm::alignTo(sizeof(OMPTargetUpdateDirective), alignof(OMPClause *)); - void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPTargetUpdateDirective *Dir = new (Mem) OMPTargetUpdateDirective(StartLoc, EndLoc, Clauses.size()); Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); return Dir; } @@ -1024,14 +1027,15 @@ OMPTargetUpdateDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { unsigned Size = llvm::alignTo(sizeof(OMPTargetUpdateDirective), alignof(OMPClause *)); - void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPTargetUpdateDirective(NumClauses); } OMPDistributeParallelForDirective *OMPDistributeParallelForDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, - const HelperExprs &Exprs) { + const HelperExprs &Exprs, bool HasCancel) { unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForDirective), alignof(OMPClause *)); void *Mem = C.Allocate( @@ -1075,6 +1079,7 @@ OMPDistributeParallelForDirective *OMPDistributeParallelForDirective::Create( Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); + Dir->HasCancel = HasCancel; return Dir; } @@ -1475,7 +1480,7 @@ OMPTeamsDistributeParallelForDirective * OMPTeamsDistributeParallelForDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, - const HelperExprs &Exprs) { + const HelperExprs &Exprs, bool HasCancel) { auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForDirective), alignof(OMPClause *)); void *Mem = C.Allocate( @@ -1519,6 +1524,7 @@ OMPTeamsDistributeParallelForDirective::Create( Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); + Dir->HasCancel = HasCancel; return Dir; } @@ -1618,7 +1624,7 @@ OMPTargetTeamsDistributeParallelForDirective * OMPTargetTeamsDistributeParallelForDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, - const HelperExprs &Exprs) { + const HelperExprs &Exprs, bool HasCancel) { auto Size = llvm::alignTo(sizeof(OMPTargetTeamsDistributeParallelForDirective), alignof(OMPClause *)); @@ -1664,6 +1670,7 @@ OMPTargetTeamsDistributeParallelForDirective::Create( Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); + Dir->HasCancel = HasCancel; return Dir; } diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 5ebaa32b49c8..d7e668a83280 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -24,6 +24,7 @@ #include "clang/AST/PrettyPrinter.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/CharInfo.h" +#include "clang/Lex/Lexer.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/Format.h" using namespace clang; @@ -38,12 +39,14 @@ namespace { unsigned IndentLevel; clang::PrinterHelper* Helper; PrintingPolicy Policy; + const ASTContext *Context; public: - StmtPrinter(raw_ostream &os, PrinterHelper* helper, - const PrintingPolicy &Policy, - unsigned Indentation = 0) - : OS(os), IndentLevel(Indentation), Helper(helper), Policy(Policy) {} + StmtPrinter(raw_ostream &os, PrinterHelper *helper, + const PrintingPolicy &Policy, unsigned Indentation = 0, + const ASTContext *Context = nullptr) + : OS(os), IndentLevel(Indentation), Helper(helper), Policy(Policy), + Context(Context) {} void PrintStmt(Stmt *S) { PrintStmt(S, Policy.Indentation); @@ -72,7 +75,8 @@ namespace { void PrintCallArgs(CallExpr *E); void PrintRawSEHExceptHandler(SEHExceptStmt *S); void PrintRawSEHFinallyStmt(SEHFinallyStmt *S); - void PrintOMPExecutableDirective(OMPExecutableDirective *S); + void PrintOMPExecutableDirective(OMPExecutableDirective *S, + bool ForceNoStmt = false); void PrintExpr(Expr *E) { if (E) @@ -859,6 +863,28 @@ void OMPClausePrinter::VisitOMPTaskReductionClause( } } +void OMPClausePrinter::VisitOMPInReductionClause(OMPInReductionClause *Node) { + if (!Node->varlist_empty()) { + OS << "in_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"; @@ -997,7 +1023,8 @@ void OMPClausePrinter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *Node) { // OpenMP directives printing methods //===----------------------------------------------------------------------===// -void StmtPrinter::PrintOMPExecutableDirective(OMPExecutableDirective *S) { +void StmtPrinter::PrintOMPExecutableDirective(OMPExecutableDirective *S, + bool ForceNoStmt) { OMPClausePrinter Printer(OS, Policy); ArrayRef<OMPClause *> Clauses = S->clauses(); for (ArrayRef<OMPClause *>::iterator I = Clauses.begin(), E = Clauses.end(); @@ -1007,7 +1034,7 @@ void StmtPrinter::PrintOMPExecutableDirective(OMPExecutableDirective *S) { OS << ' '; } OS << "\n"; - if (S->hasAssociatedStmt() && S->getAssociatedStmt()) { + if (S->hasAssociatedStmt() && S->getAssociatedStmt() && !ForceNoStmt) { assert(isa<CapturedStmt>(S->getAssociatedStmt()) && "Expected captured statement!"); Stmt *CS = cast<CapturedStmt>(S->getAssociatedStmt())->getCapturedStmt(); @@ -1136,13 +1163,13 @@ void StmtPrinter::VisitOMPTargetDataDirective(OMPTargetDataDirective *Node) { void StmtPrinter::VisitOMPTargetEnterDataDirective( OMPTargetEnterDataDirective *Node) { Indent() << "#pragma omp target enter data "; - PrintOMPExecutableDirective(Node); + PrintOMPExecutableDirective(Node, /*ForceNoStmt=*/true); } void StmtPrinter::VisitOMPTargetExitDataDirective( OMPTargetExitDataDirective *Node) { Indent() << "#pragma omp target exit data "; - PrintOMPExecutableDirective(Node); + PrintOMPExecutableDirective(Node, /*ForceNoStmt=*/true); } void StmtPrinter::VisitOMPTargetParallelDirective( @@ -1194,7 +1221,7 @@ void StmtPrinter::VisitOMPDistributeDirective(OMPDistributeDirective *Node) { void StmtPrinter::VisitOMPTargetUpdateDirective( OMPTargetUpdateDirective *Node) { Indent() << "#pragma omp target update "; - PrintOMPExecutableDirective(Node); + PrintOMPExecutableDirective(Node, /*ForceNoStmt=*/true); } void StmtPrinter::VisitOMPDistributeParallelForDirective( @@ -1294,8 +1321,7 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) { OS << "template "; OS << Node->getNameInfo(); if (Node->hasExplicitTemplateArgs()) - TemplateSpecializationType::PrintTemplateArgumentList( - OS, Node->template_arguments(), Policy); + printTemplateArgumentList(OS, Node->template_arguments(), Policy); } void StmtPrinter::VisitDependentScopeDeclRefExpr( @@ -1306,8 +1332,7 @@ void StmtPrinter::VisitDependentScopeDeclRefExpr( OS << "template "; OS << Node->getNameInfo(); if (Node->hasExplicitTemplateArgs()) - TemplateSpecializationType::PrintTemplateArgumentList( - OS, Node->template_arguments(), Policy); + printTemplateArgumentList(OS, Node->template_arguments(), Policy); } void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) { @@ -1317,14 +1342,28 @@ void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) { OS << "template "; OS << Node->getNameInfo(); if (Node->hasExplicitTemplateArgs()) - TemplateSpecializationType::PrintTemplateArgumentList( - OS, Node->template_arguments(), Policy); + printTemplateArgumentList(OS, Node->template_arguments(), Policy); +} + +static bool isImplicitSelf(const Expr *E) { + if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) { + if (const ImplicitParamDecl *PD = + dyn_cast<ImplicitParamDecl>(DRE->getDecl())) { + if (PD->getParameterKind() == ImplicitParamDecl::ObjCSelf && + DRE->getLocStart().isInvalid()) + return true; + } + } + return false; } void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) { if (Node->getBase()) { - PrintExpr(Node->getBase()); - OS << (Node->isArrow() ? "->" : "."); + if (!Policy.SuppressImplicitBase || + !isImplicitSelf(Node->getBase()->IgnoreImpCasts())) { + PrintExpr(Node->getBase()); + OS << (Node->isArrow() ? "->" : "."); + } } OS << *Node->getDecl(); } @@ -1419,7 +1458,26 @@ void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) { } } +/// Prints the given expression using the original source text. Returns true on +/// success, false otherwise. +static bool printExprAsWritten(raw_ostream &OS, Expr *E, + const ASTContext *Context) { + if (!Context) + return false; + bool Invalid = false; + StringRef Source = Lexer::getSourceText( + CharSourceRange::getTokenRange(E->getSourceRange()), + Context->getSourceManager(), Context->getLangOpts(), &Invalid); + if (!Invalid) { + OS << Source; + return true; + } + return false; +} + void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) { + if (Policy.ConstantsAsWritten && printExprAsWritten(OS, Node, Context)) + return; bool isSigned = Node->getType()->isSignedIntegerType(); OS << Node->getValue().toString(10, isSigned); @@ -1456,6 +1514,7 @@ static void PrintFloatingLiteral(raw_ostream &OS, FloatingLiteral *Node, default: llvm_unreachable("Unexpected type for float literal!"); case BuiltinType::Half: break; // FIXME: suffix? case BuiltinType::Double: break; // no suffix. + case BuiltinType::Float16: OS << "F16"; break; case BuiltinType::Float: OS << 'F'; break; case BuiltinType::LongDouble: OS << 'L'; break; case BuiltinType::Float128: OS << 'Q'; break; @@ -1463,6 +1522,8 @@ static void PrintFloatingLiteral(raw_ostream &OS, FloatingLiteral *Node, } void StmtPrinter::VisitFloatingLiteral(FloatingLiteral *Node) { + if (Policy.ConstantsAsWritten && printExprAsWritten(OS, Node, Context)) + return; PrintFloatingLiteral(OS, Node, /*PrintSuffix=*/true); } @@ -1623,16 +1684,25 @@ void StmtPrinter::VisitCallExpr(CallExpr *Call) { PrintCallArgs(Call); OS << ")"; } + +static bool isImplicitThis(const Expr *E) { + if (const auto *TE = dyn_cast<CXXThisExpr>(E)) + return TE->isImplicit(); + return false; +} + void StmtPrinter::VisitMemberExpr(MemberExpr *Node) { - // FIXME: Suppress printing implicit bases (like "this") - PrintExpr(Node->getBase()); + if (!Policy.SuppressImplicitBase || !isImplicitThis(Node->getBase())) { + PrintExpr(Node->getBase()); - MemberExpr *ParentMember = dyn_cast<MemberExpr>(Node->getBase()); - FieldDecl *ParentDecl = ParentMember - ? dyn_cast<FieldDecl>(ParentMember->getMemberDecl()) : nullptr; + MemberExpr *ParentMember = dyn_cast<MemberExpr>(Node->getBase()); + FieldDecl *ParentDecl = + ParentMember ? dyn_cast<FieldDecl>(ParentMember->getMemberDecl()) + : nullptr; - if (!ParentDecl || !ParentDecl->isAnonymousStructOrUnion()) - OS << (Node->isArrow() ? "->" : "."); + if (!ParentDecl || !ParentDecl->isAnonymousStructOrUnion()) + OS << (Node->isArrow() ? "->" : "."); + } if (FieldDecl *FD = dyn_cast<FieldDecl>(Node->getMemberDecl())) if (FD->isAnonymousStructOrUnion()) @@ -1644,8 +1714,7 @@ void StmtPrinter::VisitMemberExpr(MemberExpr *Node) { OS << "template "; OS << Node->getMemberNameInfo(); if (Node->hasExplicitTemplateArgs()) - TemplateSpecializationType::PrintTemplateArgumentList( - OS, Node->template_arguments(), Policy); + printTemplateArgumentList(OS, Node->template_arguments(), Policy); } void StmtPrinter::VisitObjCIsaExpr(ObjCIsaExpr *Node) { PrintExpr(Node->getBase()); @@ -1869,7 +1938,8 @@ void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) { // AtomicExpr stores its subexpressions in a permuted order. PrintExpr(Node->getPtr()); if (Node->getOp() != AtomicExpr::AO__c11_atomic_load && - Node->getOp() != AtomicExpr::AO__atomic_load_n) { + Node->getOp() != AtomicExpr::AO__atomic_load_n && + Node->getOp() != AtomicExpr::AO__opencl_atomic_load) { OS << ", "; PrintExpr(Node->getVal1()); } @@ -1883,7 +1953,8 @@ void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) { OS << ", "; PrintExpr(Node->getWeak()); } - if (Node->getOp() != AtomicExpr::AO__c11_atomic_init) { + if (Node->getOp() != AtomicExpr::AO__c11_atomic_init && + Node->getOp() != AtomicExpr::AO__opencl_atomic_init) { OS << ", "; PrintExpr(Node->getOrder()); } @@ -2036,8 +2107,7 @@ void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) { if (Args->size() != 1) { OS << "operator\"\"" << Node->getUDSuffix()->getName(); - TemplateSpecializationType::PrintTemplateArgumentList( - OS, Args->asArray(), Policy); + printTemplateArgumentList(OS, Args->asArray(), Policy); OS << "()"; return; } @@ -2159,6 +2229,9 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) { CEnd = Node->explicit_capture_end(); C != CEnd; ++C) { + if (C->capturesVLAType()) + continue; + if (NeedComma) OS << ", "; NeedComma = true; @@ -2361,8 +2434,7 @@ void StmtPrinter::VisitCXXDependentScopeMemberExpr( OS << "template "; OS << Node->getMemberNameInfo(); if (Node->hasExplicitTemplateArgs()) - TemplateSpecializationType::PrintTemplateArgumentList( - OS, Node->template_arguments(), Policy); + printTemplateArgumentList(OS, Node->template_arguments(), Policy); } void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) { @@ -2376,8 +2448,7 @@ void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) { OS << "template "; OS << Node->getMemberNameInfo(); if (Node->hasExplicitTemplateArgs()) - TemplateSpecializationType::PrintTemplateArgumentList( - OS, Node->template_arguments(), Policy); + printTemplateArgumentList(OS, Node->template_arguments(), Policy); } static const char *getTypeTraitName(TypeTrait TT) { @@ -2672,11 +2743,10 @@ void Stmt::dumpPretty(const ASTContext &Context) const { printPretty(llvm::errs(), nullptr, PrintingPolicy(Context.getLangOpts())); } -void Stmt::printPretty(raw_ostream &OS, - PrinterHelper *Helper, - const PrintingPolicy &Policy, - unsigned Indentation) const { - StmtPrinter P(OS, Helper, Policy, Indentation); +void Stmt::printPretty(raw_ostream &OS, PrinterHelper *Helper, + const PrintingPolicy &Policy, unsigned Indentation, + const ASTContext *Context) const { + StmtPrinter P(OS, Helper, Policy, Indentation, Context); P.Visit(const_cast<Stmt*>(this)); } diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 7ec0d1d5e017..00ef0da18bbb 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -573,6 +573,34 @@ void OMPClauseProfiler::VisitOMPTaskReductionClause( Profiler->VisitStmt(E); } } +void OMPClauseProfiler::VisitOMPInReductionClause( + const OMPInReductionClause *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); + } + for (auto *E : C->taskgroup_descriptors()) { + if (E) + Profiler->VisitStmt(E); + } +} void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) { VisitOMPClauseList(C); VistOMPClauseWithPostUpdate(C); @@ -774,6 +802,8 @@ void StmtProfiler::VisitOMPTaskwaitDirective(const OMPTaskwaitDirective *S) { void StmtProfiler::VisitOMPTaskgroupDirective(const OMPTaskgroupDirective *S) { VisitOMPExecutableDirective(S); + if (const Expr *E = S->getReductionRef()) + VisitStmt(E); } void StmtProfiler::VisitOMPFlushDirective(const OMPFlushDirective *S) { @@ -1354,6 +1384,10 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S, case OO_GreaterEqual: BinaryOp = BO_GE; return Stmt::BinaryOperatorClass; + + case OO_Spaceship: + // FIXME: Update this once we support <=> expressions. + llvm_unreachable("<=> expressions not supported yet"); case OO_AmpAmp: BinaryOp = BO_LAnd; @@ -1388,7 +1422,7 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S, llvm_unreachable("Invalid overloaded operator expression"); } -#if defined(_MSC_VER) +#if defined(_MSC_VER) && !defined(__clang__) #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 @@ -1429,7 +1463,7 @@ void StmtProfiler::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) { ID.AddInteger(S->getOperator()); } -#if defined(_MSC_VER) +#if defined(_MSC_VER) && !defined(__clang__) #if _MSC_VER == 1911 #pragma optimize("", on) #endif @@ -1560,6 +1594,9 @@ StmtProfiler::VisitLambdaExpr(const LambdaExpr *S) { for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(), CEnd = S->explicit_capture_end(); C != CEnd; ++C) { + if (C->capturesVLAType()) + continue; + ID.AddInteger(C->getCaptureKind()); switch (C->getCaptureKind()) { case LCK_StarThis: @@ -1671,6 +1708,7 @@ void StmtProfiler::VisitCXXUnresolvedConstructExpr( const CXXUnresolvedConstructExpr *S) { VisitExpr(S); VisitType(S->getTypeAsWritten()); + ID.AddInteger(S->isListInitialization()); } void StmtProfiler::VisitCXXDependentScopeMemberExpr( diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp index e4998c37a4ef..e81c11a77825 100644 --- a/lib/AST/TemplateBase.cpp +++ b/lib/AST/TemplateBase.cpp @@ -1,4 +1,4 @@ -//===--- TemplateBase.cpp - Common template AST class implementation ------===// +//===- TemplateBase.cpp - Common template AST class implementation --------===// // // The LLVM Compiler Infrastructure // @@ -14,17 +14,32 @@ #include "clang/AST/TemplateBase.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/PrettyPrinter.h" +#include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/APSInt.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <cstring> using namespace clang; @@ -37,7 +52,7 @@ using namespace clang; /// \param Policy the printing policy for EnumConstantDecl printing. static void printIntegral(const TemplateArgument &TemplArg, raw_ostream &Out, const PrintingPolicy& Policy) { - const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr(); + const Type *T = TemplArg.getIntegralType().getTypePtr(); const llvm::APSInt &Val = TemplArg.getAsIntegral(); if (const EnumType *ET = T->getAs<EnumType>()) { @@ -415,10 +430,9 @@ void TemplateArgument::print(const PrintingPolicy &Policy, Out << "..."; break; - case Integral: { + case Integral: printIntegral(*this, Out, Policy); break; - } case Expression: getAsExpr()->printPretty(Out, nullptr, Policy); diff --git a/lib/AST/TemplateName.cpp b/lib/AST/TemplateName.cpp index 47a7d47e7a48..bd04fd8366b3 100644 --- a/lib/AST/TemplateName.cpp +++ b/lib/AST/TemplateName.cpp @@ -1,4 +1,4 @@ -//===--- TemplateName.cpp - C++ Template Name Representation---------------===// +//===- TemplateName.cpp - C++ Template Name Representation ----------------===// // // The LLVM Compiler Infrastructure // @@ -12,15 +12,24 @@ //===----------------------------------------------------------------------===// #include "clang/AST/TemplateName.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/TemplateBase.h" #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" +#include "clang/Basic/OperatorKinds.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <string> + using namespace clang; -using namespace llvm; TemplateArgument SubstTemplateTemplateParmPackStorage::getArgumentPack() const { @@ -131,6 +140,23 @@ DependentTemplateName *TemplateName::getAsDependentTemplateName() const { return Storage.dyn_cast<DependentTemplateName *>(); } +TemplateName TemplateName::getNameToSubstitute() const { + TemplateDecl *Decl = getAsTemplateDecl(); + + // Substituting a dependent template name: preserve it as written. + if (!Decl) + return *this; + + // If we have a template declaration, use the most recent non-friend + // declaration of that template. + Decl = cast<TemplateDecl>(Decl->getMostRecentDecl()); + while (Decl->getFriendObjectKind()) { + Decl = cast<TemplateDecl>(Decl->getPreviousDecl()); + assert(Decl && "all declarations of template are friends"); + } + return TemplateName(Decl); +} + bool TemplateName::isDependent() const { if (TemplateDecl *Template = getAsTemplateDecl()) { if (isa<TemplateTemplateParmDecl>(Template)) @@ -209,7 +235,7 @@ TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, TemplateName N) { std::string NameStr; - raw_string_ostream OS(NameStr); + llvm::raw_string_ostream OS(NameStr); LangOptions LO; LO.CPlusPlus = true; LO.Bool = true; diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index d21781dc3899..38f2a16fa16f 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1,4 +1,4 @@ -//===--- Type.cpp - Type representation and manipulation ------------------===// +//===- Type.cpp - Type representation and manipulation --------------------===// // // The LLVM Compiler Infrastructure // @@ -12,20 +12,44 @@ //===----------------------------------------------------------------------===// #include "clang/AST/Type.h" +#include "Linkage.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" #include "clang/AST/CharUnits.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" +#include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/PrettyPrinter.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/TemplateName.h" #include "clang/AST/TypeVisitor.h" +#include "clang/Basic/AddressSpaces.h" +#include "clang/Basic/ExceptionSpecificationType.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/Linkage.h" #include "clang/Basic/Specifiers.h" +#include "clang/Basic/TargetCXXABI.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Basic/Visibility.h" +#include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" -#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" #include <algorithm> +#include <cassert> +#include <cstdint> +#include <cstring> + using namespace clang; bool Qualifiers::isStrictSupersetOf(Qualifiers Other) const { @@ -125,12 +149,10 @@ DependentSizedArrayType::DependentSizedArrayType(const ASTContext &Context, Expr *e, ArraySizeModifier sm, unsigned tq, SourceRange brackets) - : ArrayType(DependentSizedArray, et, can, sm, tq, + : ArrayType(DependentSizedArray, et, can, sm, tq, (et->containsUnexpandedParameterPack() || (e && e->containsUnexpandedParameterPack()))), - Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) -{ -} + Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) {} void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, @@ -152,13 +174,11 @@ DependentSizedExtVectorType::DependentSizedExtVectorType(const SourceLocation loc) : Type(DependentSizedExtVector, can, /*Dependent=*/true, /*InstantiationDependent=*/true, - ElementType->isVariablyModifiedType(), + ElementType->isVariablyModifiedType(), (ElementType->containsUnexpandedParameterPack() || (SizeExpr && SizeExpr->containsUnexpandedParameterPack()))), Context(Context), SizeExpr(SizeExpr), ElementType(ElementType), - loc(loc) -{ -} + loc(loc) {} void DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID, @@ -168,18 +188,37 @@ DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID, SizeExpr->Profile(ID, Context, true); } +DependentAddressSpaceType::DependentAddressSpaceType( + const ASTContext &Context, QualType PointeeType, QualType can, + Expr *AddrSpaceExpr, SourceLocation loc) + : Type(DependentAddressSpace, can, /*Dependent=*/true, + /*InstantiationDependent=*/true, + PointeeType->isVariablyModifiedType(), + (PointeeType->containsUnexpandedParameterPack() || + (AddrSpaceExpr && + AddrSpaceExpr->containsUnexpandedParameterPack()))), + Context(Context), AddrSpaceExpr(AddrSpaceExpr), PointeeType(PointeeType), + loc(loc) {} + +void DependentAddressSpaceType::Profile(llvm::FoldingSetNodeID &ID, + const ASTContext &Context, + QualType PointeeType, + Expr *AddrSpaceExpr) { + ID.AddPointer(PointeeType.getAsOpaquePtr()); + AddrSpaceExpr->Profile(ID, Context, true); +} + VectorType::VectorType(QualType vecType, unsigned nElements, QualType canonType, VectorKind vecKind) : VectorType(Vector, vecType, nElements, canonType, vecKind) {} VectorType::VectorType(TypeClass tc, QualType vecType, unsigned nElements, QualType canonType, VectorKind vecKind) - : Type(tc, canonType, vecType->isDependentType(), - vecType->isInstantiationDependentType(), - vecType->isVariablyModifiedType(), - vecType->containsUnexpandedParameterPack()), - ElementType(vecType) -{ + : Type(tc, canonType, vecType->isDependentType(), + vecType->isInstantiationDependentType(), + vecType->isVariablyModifiedType(), + vecType->containsUnexpandedParameterPack()), + ElementType(vecType) { VectorTypeBits.VecKind = vecKind; VectorTypeBits.NumElements = nElements; } @@ -354,11 +393,13 @@ const Type *Type::getUnqualifiedDesugaredType() const { } } } + bool Type::isClassType() const { if (const RecordType *RT = getAs<RecordType>()) return RT->getDecl()->isClass(); return false; } + bool Type::isStructureType() const { if (const RecordType *RT = getAs<RecordType>()) return RT->getDecl()->isStruct(); @@ -381,6 +422,7 @@ bool Type::isStructureOrClassType() const { } return false; } + bool Type::isVoidPointerType() const { if (const PointerType *PT = getAs<PointerType>()) return PT->getPointeeType()->isVoidType(); @@ -534,12 +576,11 @@ bool Type::isObjCInertUnsafeUnretainedType() const { ObjCTypeParamType::ObjCTypeParamType(const ObjCTypeParamDecl *D, QualType can, ArrayRef<ObjCProtocolDecl *> protocols) - : Type(ObjCTypeParam, can, can->isDependentType(), - can->isInstantiationDependentType(), - can->isVariablyModifiedType(), - /*ContainsUnexpandedParameterPack=*/false), - OTPDecl(const_cast<ObjCTypeParamDecl*>(D)) -{ + : Type(ObjCTypeParam, can, can->isDependentType(), + can->isInstantiationDependentType(), + can->isVariablyModifiedType(), + /*ContainsUnexpandedParameterPack=*/false), + OTPDecl(const_cast<ObjCTypeParamDecl*>(D)) { initialize(protocols); } @@ -547,12 +588,11 @@ ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base, ArrayRef<QualType> typeArgs, ArrayRef<ObjCProtocolDecl *> protocols, bool isKindOf) - : Type(ObjCObject, Canonical, Base->isDependentType(), - Base->isInstantiationDependentType(), - Base->isVariablyModifiedType(), - Base->containsUnexpandedParameterPack()), - BaseType(Base) -{ + : Type(ObjCObject, Canonical, Base->isDependentType(), + Base->isInstantiationDependentType(), + Base->isVariablyModifiedType(), + Base->containsUnexpandedParameterPack()), + BaseType(Base) { ObjCObjectTypeBits.IsKindOf = isKindOf; ObjCObjectTypeBits.NumTypeArgs = typeArgs.size(); @@ -603,13 +643,13 @@ ArrayRef<QualType> ObjCObjectType::getTypeArgs() const { if (auto objcObject = getBaseType()->getAs<ObjCObjectType>()) { // Terminate when we reach an interface type. if (isa<ObjCInterfaceType>(objcObject)) - return { }; + return {}; return objcObject->getTypeArgs(); } // No type arguments. - return { }; + return {}; } bool ObjCObjectType::isKindOfType() const { @@ -645,7 +685,7 @@ QualType ObjCObjectType::stripObjCKindOfTypeAndQuals( return ctx.getObjCObjectType(ctx.getQualifiedType(baseType, splitBaseType.Quals), getTypeArgsAsWritten(), - /*protocols=*/{ }, + /*protocols=*/{}, /*isKindOf=*/false); } @@ -658,10 +698,10 @@ const ObjCObjectPointerType *ObjCObjectPointerType::stripObjCKindOfTypeAndQuals( return ctx.getObjCObjectPointerType(obj)->castAs<ObjCObjectPointerType>(); } -namespace { - template<typename F> -QualType simpleTransform(ASTContext &ctx, QualType type, F &&f); +static QualType simpleTransform(ASTContext &ctx, QualType type, F &&f); + +namespace { /// Visitor used by simpleTransform() to perform the transformation. template<typename F> @@ -675,7 +715,8 @@ struct SimpleTransformVisitor } public: - SimpleTransformVisitor(ASTContext &ctx, F &&f) : Ctx(ctx), TheFunc(std::move(f)) { } + SimpleTransformVisitor(ASTContext &ctx, F &&f) + : Ctx(ctx), TheFunc(std::move(f)) {} // None of the clients of this transformation can occur where // there are dependent types, so skip dependent types. @@ -1044,10 +1085,12 @@ public: #undef TRIVIAL_TYPE_CLASS }; +} // namespace + /// Perform a simple type transformation that does not change the /// semantics of the type. template<typename F> -QualType simpleTransform(ASTContext &ctx, QualType type, F &&f) { +static QualType simpleTransform(ASTContext &ctx, QualType type, F &&f) { // Transform the type. If it changed, return the transformed result. QualType transformed = f(type); if (transformed.getAsOpaquePtr() != type.getAsOpaquePtr()) @@ -1067,8 +1110,6 @@ QualType simpleTransform(ASTContext &ctx, QualType type, F &&f) { return ctx.getQualifiedType(result, splitType.Quals); } -} // end anonymous namespace - /// Substitute the given type arguments for Objective-C type /// parameters within the given type, recursively. QualType QualType::substObjCTypeArgs( @@ -1233,7 +1274,7 @@ QualType QualType::substObjCTypeArgs( if (typeArgs.empty() && context != ObjCSubstitutionContext::Superclass) { return ctx.getObjCObjectType( - objcObjectType->getBaseType(), { }, + objcObjectType->getBaseType(), {}, protocols, objcObjectType->isKindOfTypeAsWritten()); } @@ -1343,7 +1384,7 @@ Optional<ArrayRef<QualType>> Type::getObjCSubstitutions( objectType = objectPointerType->getObjectType(); } else if (getAs<BlockPointerType>()) { ASTContext &ctx = dc->getParentASTContext(); - objectType = ctx.getObjCObjectType(ctx.ObjCBuiltinIdTy, { }, { }) + objectType = ctx.getObjCObjectType(ctx.ObjCBuiltinIdTy, {}, {}) ->castAs<ObjCObjectType>(); } else { objectType = getAs<ObjCObjectType>(); @@ -1522,6 +1563,7 @@ const ObjCObjectType *Type::getAsObjCInterfaceType() const { } return nullptr; } + const ObjCObjectPointerType *Type::getAsObjCInterfacePointerType() const { if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) { if (OPT->getInterfaceType()) @@ -1559,14 +1601,17 @@ TagDecl *Type::getAsTagDecl() const { } namespace { + class GetContainedDeducedTypeVisitor : public TypeVisitor<GetContainedDeducedTypeVisitor, Type*> { bool Syntactic; + public: GetContainedDeducedTypeVisitor(bool Syntactic = false) : Syntactic(Syntactic) {} using TypeVisitor<GetContainedDeducedTypeVisitor, Type*>::Visit; + Type *Visit(QualType T) { if (T.isNull()) return nullptr; @@ -1579,50 +1624,64 @@ namespace { } // Only these types can contain the desired 'auto' type. + Type *VisitElaboratedType(const ElaboratedType *T) { return Visit(T->getNamedType()); } + Type *VisitPointerType(const PointerType *T) { return Visit(T->getPointeeType()); } + Type *VisitBlockPointerType(const BlockPointerType *T) { return Visit(T->getPointeeType()); } + Type *VisitReferenceType(const ReferenceType *T) { return Visit(T->getPointeeTypeAsWritten()); } + Type *VisitMemberPointerType(const MemberPointerType *T) { return Visit(T->getPointeeType()); } + Type *VisitArrayType(const ArrayType *T) { return Visit(T->getElementType()); } + Type *VisitDependentSizedExtVectorType( const DependentSizedExtVectorType *T) { return Visit(T->getElementType()); } + Type *VisitVectorType(const VectorType *T) { return Visit(T->getElementType()); } + 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()); } + Type *VisitParenType(const ParenType *T) { return Visit(T->getInnerType()); } + Type *VisitAttributedType(const AttributedType *T) { return Visit(T->getModifiedType()); } + Type *VisitAdjustedType(const AdjustedType *T) { return Visit(T->getOriginalType()); } }; -} + +} // namespace DeducedType *Type::getContainedDeducedType() const { return cast_or_null<DeducedType>( @@ -1673,7 +1732,6 @@ bool Type::isIntegralType(const ASTContext &Ctx) const { return false; } - bool Type::isIntegralOrUnscopedEnumerationType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && @@ -1689,8 +1747,6 @@ bool Type::isIntegralOrUnscopedEnumerationType() const { return false; } - - bool Type::isCharType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() == BuiltinType::Char_U || @@ -2015,7 +2071,7 @@ bool QualType::isCXX98PODType(const ASTContext &Context) const { // We return false for that case. Except for incomplete arrays of PODs, which // are PODs according to the standard. if (isNull()) - return 0; + return false; if ((*this)->isIncompleteArrayType()) return Context.getBaseElementType(*this).isCXX98PODType(Context); @@ -2063,7 +2119,7 @@ bool QualType::isTrivialType(const ASTContext &Context) const { // We return false for that case. Except for incomplete arrays of PODs, which // are PODs according to the standard. if (isNull()) - return 0; + return false; if ((*this)->isArrayType()) return Context.getBaseElementType(*this).isTrivialType(Context); @@ -2563,6 +2619,8 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const { return "double"; case LongDouble: return "long double"; + case Float16: + return "_Float16"; case Float128: return "__float128"; case WChar_S: @@ -2835,7 +2893,6 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, const QualType *ArgTys, unsigned NumParams, const ExtProtoInfo &epi, const ASTContext &Context, bool Canonical) { - // We have to be careful not to get ambiguous profile encodings. // Note that valid type pointers are never ambiguous with anything else. // @@ -2897,12 +2954,11 @@ QualType TypedefType::desugar() const { } TypeOfExprType::TypeOfExprType(Expr *E, QualType can) - : Type(TypeOfExpr, can, E->isTypeDependent(), - E->isInstantiationDependent(), - E->getType()->isVariablyModifiedType(), - E->containsUnexpandedParameterPack()), - TOExpr(E) { -} + : Type(TypeOfExpr, can, E->isTypeDependent(), + E->isInstantiationDependent(), + E->getType()->isVariablyModifiedType(), + E->containsUnexpandedParameterPack()), + TOExpr(E) {} bool TypeOfExprType::isSugared() const { return !TOExpr->isTypeDependent(); @@ -2924,13 +2980,11 @@ DecltypeType::DecltypeType(Expr *E, QualType underlyingType, QualType can) // C++11 [temp.type]p2: "If an expression e involves a template parameter, // decltype(e) denotes a unique dependent type." Hence a decltype type is // type-dependent even if its expression is only instantiation-dependent. - : Type(Decltype, can, E->isInstantiationDependent(), - E->isInstantiationDependent(), - E->getType()->isVariablyModifiedType(), - E->containsUnexpandedParameterPack()), - E(E), - UnderlyingType(underlyingType) { -} + : Type(Decltype, can, E->isInstantiationDependent(), + E->isInstantiationDependent(), + E->getType()->isVariablyModifiedType(), + E->containsUnexpandedParameterPack()), + E(E), UnderlyingType(underlyingType) {} bool DecltypeType::isSugared() const { return !E->isInstantiationDependent(); } @@ -2942,7 +2996,7 @@ QualType DecltypeType::desugar() const { } DependentDecltypeType::DependentDecltypeType(const ASTContext &Context, Expr *E) - : DecltypeType(E, Context.DependentTy), Context(Context) { } + : DecltypeType(E, Context.DependentTy), Context(Context) {} void DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, Expr *E) { @@ -2953,26 +3007,23 @@ UnaryTransformType::UnaryTransformType(QualType BaseType, QualType UnderlyingType, UTTKind UKind, QualType CanonicalType) - : Type(UnaryTransform, CanonicalType, BaseType->isDependentType(), - BaseType->isInstantiationDependentType(), - BaseType->isVariablyModifiedType(), - BaseType->containsUnexpandedParameterPack()) - , BaseType(BaseType), UnderlyingType(UnderlyingType), UKind(UKind) -{} + : Type(UnaryTransform, CanonicalType, BaseType->isDependentType(), + BaseType->isInstantiationDependentType(), + BaseType->isVariablyModifiedType(), + BaseType->containsUnexpandedParameterPack()), + BaseType(BaseType), UnderlyingType(UnderlyingType), UKind(UKind) {} DependentUnaryTransformType::DependentUnaryTransformType(const ASTContext &C, QualType BaseType, UTTKind UKind) - : UnaryTransformType(BaseType, C.DependentTy, UKind, QualType()) -{} - + : UnaryTransformType(BaseType, C.DependentTy, UKind, QualType()) {} TagType::TagType(TypeClass TC, const TagDecl *D, QualType can) - : Type(TC, can, D->isDependentType(), - /*InstantiationDependent=*/D->isDependentType(), - /*VariablyModified=*/false, - /*ContainsUnexpandedParameterPack=*/false), - decl(const_cast<TagDecl*>(D)) {} + : Type(TC, can, D->isDependentType(), + /*InstantiationDependent=*/D->isDependentType(), + /*VariablyModified=*/false, + /*ContainsUnexpandedParameterPack=*/false), + decl(const_cast<TagDecl*>(D)) {} static TagDecl *getInterestingTagDecl(TagDecl *decl) { for (auto I : decl->redecls()) { @@ -2991,6 +3042,19 @@ bool TagType::isBeingDefined() const { return getDecl()->isBeingDefined(); } +bool RecordType::hasConstFields() const { + for (FieldDecl *FD : getDecl()->fields()) { + QualType FieldTy = FD->getType(); + if (FieldTy.isConstQualified()) + return true; + FieldTy = FieldTy.getCanonicalType(); + if (const RecordType *FieldRecTy = FieldTy->getAs<RecordType>()) + if (FieldRecTy->hasConstFields()) + return true; + } + return false; +} + bool AttributedType::isQualifier() const { switch (getAttrKind()) { // These are type qualifiers in the traditional C sense: they annotate @@ -3104,11 +3168,9 @@ SubstTemplateTypeParmPackType:: SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param, QualType Canon, const TemplateArgument &ArgPack) - : Type(SubstTemplateTypeParmPack, Canon, true, true, false, true), - Replaced(Param), - Arguments(ArgPack.pack_begin()), NumArguments(ArgPack.pack_size()) -{ -} + : Type(SubstTemplateTypeParmPack, Canon, true, true, false, true), + Replaced(Param), + Arguments(ArgPack.pack_begin()), NumArguments(ArgPack.pack_size()) {} TemplateArgument SubstTemplateTypeParmPackType::getArgumentPack() const { return TemplateArgument(llvm::makeArrayRef(Arguments, NumArguments)); @@ -3275,11 +3337,13 @@ public: L.hasLocalOrUnnamedType() | R.hasLocalOrUnnamedType()); } }; -} + +} // namespace static CachedProperties computeCachedProperties(const Type *T); namespace clang { + /// The type-property cache. This is templated so as to be /// instantiated at an internal type to prevent unnecessary symbol /// leakage. @@ -3317,13 +3381,19 @@ public: T->TypeBits.CachedLocalOrUnnamed = Result.hasLocalOrUnnamedType(); } }; -} + +} // namespace clang // Instantiate the friend template at a private class. In a // reasonable implementation, these symbols will be internal. // It is terrible that this is the best way to accomplish this. -namespace { class Private {}; } -typedef TypePropertyCache<Private> Cache; +namespace { + +class Private {}; + +} // namespace + +using Cache = TypePropertyCache<Private>; static CachedProperties computeCachedProperties(const Type *T) { switch (T->getTypeClass()) { @@ -3428,9 +3498,7 @@ bool Type::hasUnnamedOrLocalType() const { return TypeBits.hasLocalOrUnnamedType(); } -static LinkageInfo computeLinkageInfo(QualType T); - -static LinkageInfo computeLinkageInfo(const Type *T) { +LinkageInfo LinkageComputer::computeTypeLinkageInfo(const Type *T) { switch (T->getTypeClass()) { #define TYPE(Class,Base) #define NON_CANONICAL_TYPE(Class,Base) case Type::Class: @@ -3454,75 +3522,78 @@ static LinkageInfo computeLinkageInfo(const Type *T) { case Type::Record: case Type::Enum: - return cast<TagType>(T)->getDecl()->getLinkageAndVisibility(); + return getDeclLinkageAndVisibility(cast<TagType>(T)->getDecl()); case Type::Complex: - return computeLinkageInfo(cast<ComplexType>(T)->getElementType()); + return computeTypeLinkageInfo(cast<ComplexType>(T)->getElementType()); case Type::Pointer: - return computeLinkageInfo(cast<PointerType>(T)->getPointeeType()); + return computeTypeLinkageInfo(cast<PointerType>(T)->getPointeeType()); case Type::BlockPointer: - return computeLinkageInfo(cast<BlockPointerType>(T)->getPointeeType()); + return computeTypeLinkageInfo(cast<BlockPointerType>(T)->getPointeeType()); case Type::LValueReference: case Type::RValueReference: - return computeLinkageInfo(cast<ReferenceType>(T)->getPointeeType()); + return computeTypeLinkageInfo(cast<ReferenceType>(T)->getPointeeType()); case Type::MemberPointer: { const MemberPointerType *MPT = cast<MemberPointerType>(T); - LinkageInfo LV = computeLinkageInfo(MPT->getClass()); - LV.merge(computeLinkageInfo(MPT->getPointeeType())); + LinkageInfo LV = computeTypeLinkageInfo(MPT->getClass()); + LV.merge(computeTypeLinkageInfo(MPT->getPointeeType())); return LV; } case Type::ConstantArray: case Type::IncompleteArray: case Type::VariableArray: - return computeLinkageInfo(cast<ArrayType>(T)->getElementType()); + return computeTypeLinkageInfo(cast<ArrayType>(T)->getElementType()); case Type::Vector: case Type::ExtVector: - return computeLinkageInfo(cast<VectorType>(T)->getElementType()); + return computeTypeLinkageInfo(cast<VectorType>(T)->getElementType()); case Type::FunctionNoProto: - return computeLinkageInfo(cast<FunctionType>(T)->getReturnType()); + return computeTypeLinkageInfo(cast<FunctionType>(T)->getReturnType()); case Type::FunctionProto: { const FunctionProtoType *FPT = cast<FunctionProtoType>(T); - LinkageInfo LV = computeLinkageInfo(FPT->getReturnType()); + LinkageInfo LV = computeTypeLinkageInfo(FPT->getReturnType()); for (const auto &ai : FPT->param_types()) - LV.merge(computeLinkageInfo(ai)); + LV.merge(computeTypeLinkageInfo(ai)); return LV; } case Type::ObjCInterface: - return cast<ObjCInterfaceType>(T)->getDecl()->getLinkageAndVisibility(); + return getDeclLinkageAndVisibility(cast<ObjCInterfaceType>(T)->getDecl()); case Type::ObjCObject: - return computeLinkageInfo(cast<ObjCObjectType>(T)->getBaseType()); + return computeTypeLinkageInfo(cast<ObjCObjectType>(T)->getBaseType()); case Type::ObjCObjectPointer: - return computeLinkageInfo(cast<ObjCObjectPointerType>(T)->getPointeeType()); + return computeTypeLinkageInfo( + cast<ObjCObjectPointerType>(T)->getPointeeType()); case Type::Atomic: - return computeLinkageInfo(cast<AtomicType>(T)->getValueType()); + return computeTypeLinkageInfo(cast<AtomicType>(T)->getValueType()); case Type::Pipe: - return computeLinkageInfo(cast<PipeType>(T)->getElementType()); + return computeTypeLinkageInfo(cast<PipeType>(T)->getElementType()); } llvm_unreachable("unhandled type class"); } -static LinkageInfo computeLinkageInfo(QualType T) { - return computeLinkageInfo(T.getTypePtr()); -} - bool Type::isLinkageValid() const { if (!TypeBits.isCacheValid()) return true; - return computeLinkageInfo(getCanonicalTypeInternal()).getLinkage() == - TypeBits.getLinkage(); + Linkage L = LinkageComputer{} + .computeTypeLinkageInfo(getCanonicalTypeInternal()) + .getLinkage(); + return L == TypeBits.getLinkage(); } -LinkageInfo Type::getLinkageAndVisibility() const { - if (!isCanonicalUnqualified()) - return computeLinkageInfo(getCanonicalTypeInternal()); +LinkageInfo LinkageComputer::getTypeLinkageAndVisibility(const Type *T) { + if (!T->isCanonicalUnqualified()) + return computeTypeLinkageInfo(T->getCanonicalTypeInternal()); - LinkageInfo LV = computeLinkageInfo(this); - assert(LV.getLinkage() == getLinkage()); + LinkageInfo LV = computeTypeLinkageInfo(T); + assert(LV.getLinkage() == T->getLinkage()); return LV; } +LinkageInfo Type::getLinkageAndVisibility() const { + return LinkageComputer{}.getTypeLinkageAndVisibility(this); +} + Optional<NullabilityKind> Type::getNullability(const ASTContext &context) const { QualType type(this, 0); do { @@ -3634,6 +3705,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: + case Type::DependentAddressSpace: case Type::FunctionProto: case Type::FunctionNoProto: case Type::Record: @@ -3748,11 +3820,13 @@ bool Type::isObjCIndependentClassType() const { return typedefType->getDecl()->hasAttr<ObjCIndependentClassAttr>(); return false; } + bool Type::isObjCRetainableType() const { return isObjCObjectPointerType() || isBlockPointerType() || isObjCNSObjectType(); } + bool Type::isObjCIndirectLifetimeType() const { if (isObjCLifetimeType()) return true; diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp index c9a268655723..b05c5fc68096 100644 --- a/lib/AST/TypeLoc.cpp +++ b/lib/AST/TypeLoc.cpp @@ -1,4 +1,4 @@ -//===--- TypeLoc.cpp - Type Source Info Wrapper -----------------*- C++ -*-===// +//===- TypeLoc.cpp - Type Source Info Wrapper -----------------------------===// // // The LLVM Compiler Infrastructure // @@ -14,8 +14,19 @@ #include "clang/AST/TypeLoc.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/TemplateName.h" #include "clang/AST/TypeLocVisitor.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <cstring> + using namespace clang; static const unsigned TypeLocMaxDataAlign = alignof(void *); @@ -25,16 +36,18 @@ static const unsigned TypeLocMaxDataAlign = alignof(void *); //===----------------------------------------------------------------------===// namespace { - class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> { - public: + +class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> { +public: #define ABSTRACT_TYPELOC(CLASS, PARENT) #define TYPELOC(CLASS, PARENT) \ - SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ - return TyLoc.getLocalSourceRange(); \ - } + SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ + return TyLoc.getLocalSourceRange(); \ + } #include "clang/AST/TypeLocNodes.def" - }; -} +}; + +} // namespace SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) { if (TL.isNull()) return SourceRange(); @@ -42,16 +55,18 @@ SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) { } namespace { - class TypeAligner : public TypeLocVisitor<TypeAligner, unsigned> { - public: + +class TypeAligner : public TypeLocVisitor<TypeAligner, unsigned> { +public: #define ABSTRACT_TYPELOC(CLASS, PARENT) #define TYPELOC(CLASS, PARENT) \ - unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ - return TyLoc.getLocalDataAlignment(); \ - } + unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ + return TyLoc.getLocalDataAlignment(); \ + } #include "clang/AST/TypeLocNodes.def" - }; -} +}; + +} // namespace /// \brief Returns the alignment of the type source info data block. unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) { @@ -60,16 +75,18 @@ unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) { } namespace { - class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> { - public: + +class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> { +public: #define ABSTRACT_TYPELOC(CLASS, PARENT) #define TYPELOC(CLASS, PARENT) \ - unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ - return TyLoc.getLocalDataSize(); \ - } + unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ + return TyLoc.getLocalDataSize(); \ + } #include "clang/AST/TypeLocNodes.def" - }; -} +}; + +} // namespace /// \brief Returns the size of the type source info data block. unsigned TypeLoc::getFullDataSizeForType(QualType Ty) { @@ -88,16 +105,18 @@ unsigned TypeLoc::getFullDataSizeForType(QualType Ty) { } namespace { - class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> { - public: + +class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> { +public: #define ABSTRACT_TYPELOC(CLASS, PARENT) #define TYPELOC(CLASS, PARENT) \ - TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ - return TyLoc.getNextTypeLoc(); \ - } + TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ + return TyLoc.getNextTypeLoc(); \ + } #include "clang/AST/TypeLocNodes.def" - }; -} +}; + +} // namespace /// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the /// TypeLoc is a PointerLoc and next TypeLoc is for "int". @@ -127,20 +146,22 @@ void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL, } namespace { - class TypeLocCopier : public TypeLocVisitor<TypeLocCopier> { - TypeLoc Source; - public: - TypeLocCopier(TypeLoc source) : Source(source) { } + +class TypeLocCopier : public TypeLocVisitor<TypeLocCopier> { + TypeLoc Source; + +public: + TypeLocCopier(TypeLoc source) : Source(source) {} #define ABSTRACT_TYPELOC(CLASS, PARENT) #define TYPELOC(CLASS, PARENT) \ - void Visit##CLASS##TypeLoc(CLASS##TypeLoc dest) { \ - dest.copyLocal(Source.castAs<CLASS##TypeLoc>()); \ - } + void Visit##CLASS##TypeLoc(CLASS##TypeLoc dest) { \ + dest.copyLocal(Source.castAs<CLASS##TypeLoc>()); \ + } #include "clang/AST/TypeLocNodes.def" - }; -} +}; +} // namespace void TypeLoc::copy(TypeLoc other) { assert(getFullDataSize() == other.getFullDataSize()); @@ -243,22 +264,22 @@ SourceLocation TypeLoc::getEndLoc() const { } } - namespace { - struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> { - // Overload resolution does the real work for us. - static bool isTypeSpec(TypeSpecTypeLoc _) { return true; } - static bool isTypeSpec(TypeLoc _) { return false; } + +struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> { + // Overload resolution does the real work for us. + static bool isTypeSpec(TypeSpecTypeLoc _) { return true; } + static bool isTypeSpec(TypeLoc _) { return false; } #define ABSTRACT_TYPELOC(CLASS, PARENT) #define TYPELOC(CLASS, PARENT) \ - bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ - return isTypeSpec(TyLoc); \ - } + bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ + return isTypeSpec(TyLoc); \ + } #include "clang/AST/TypeLocNodes.def" - }; -} +}; +} // namespace /// \brief Determines if the given type loc corresponds to a /// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in @@ -319,6 +340,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { case BuiltinType::Float: case BuiltinType::Double: case BuiltinType::LongDouble: + case BuiltinType::Float16: case BuiltinType::Float128: llvm_unreachable("Builtin type needs extra local data!"); // Fall through, if the impossible happens. @@ -363,7 +385,7 @@ SourceLocation TypeLoc::findNullabilityLoc() const { return attributedLoc.getAttrNameLoc(); } - return SourceLocation(); + return {}; } TypeLoc TypeLoc::findExplicitQualifierLoc() const { @@ -384,7 +406,7 @@ TypeLoc TypeLoc::findExplicitQualifierLoc() const { return atomic; } - return TypeLoc(); + return {}; } void ObjCTypeParamTypeLoc::initializeLocal(ASTContext &Context, @@ -422,6 +444,15 @@ void TypeOfTypeLoc::initializeLocal(ASTContext &Context, getUnderlyingType(), Loc); } +void UnaryTransformTypeLoc::initializeLocal(ASTContext &Context, + SourceLocation Loc) { + setKWLoc(Loc); + setRParenLoc(Loc); + setLParenLoc(Loc); + this->setUnderlyingTInfo( + Context.getTrivialTypeSourceInfo(getTypePtr()->getBaseType(), Loc)); +} + void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) { setElaboratedKeywordLoc(Loc); diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 15c63bf4ed98..35e0b75f3c22 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -222,6 +222,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::LValueReference: case Type::RValueReference: case Type::MemberPointer: + case Type::DependentAddressSpace: case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: @@ -527,6 +528,19 @@ void TypePrinter::printDependentSizedArrayAfter( printAfter(T->getElementType(), OS); } +void TypePrinter::printDependentAddressSpaceBefore( + const DependentAddressSpaceType *T, raw_ostream &OS) { + printBefore(T->getPointeeType(), OS); +} +void TypePrinter::printDependentAddressSpaceAfter( + const DependentAddressSpaceType *T, raw_ostream &OS) { + OS << " __attribute__((address_space("; + if (T->getAddrSpaceExpr()) + T->getAddrSpaceExpr()->printPretty(OS, nullptr, Policy); + OS << ")))"; + printAfter(T->getPointeeType(), OS); +} + void TypePrinter::printDependentSizedExtVectorBefore( const DependentSizedExtVectorType *T, raw_ostream &OS) { @@ -665,6 +679,8 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, auto EPI = T->getExtParameterInfo(i); if (EPI.isConsumed()) OS << "__attribute__((ns_consumed)) "; + if (EPI.isNoEscape()) + OS << "__attribute__((noescape)) "; auto ABI = EPI.getABI(); if (ABI != ParameterABI::Ordinary) OS << "__attribute__((" << getParameterABISpelling(ABI) << ")) "; @@ -966,8 +982,7 @@ void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); OS << Spec->getIdentifier()->getName(); const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - TemplateSpecializationType::PrintTemplateArgumentList( - OS, TemplateArgs.asArray(), Policy); + printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy); OS << "::"; } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) { if (TypedefNameDecl *Typedef = Tag->getTypedefNameForAnonDecl()) @@ -1054,7 +1069,7 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) { Args = TemplateArgs.asArray(); } IncludeStrongLifetimeRAII Strong(Policy); - TemplateSpecializationType::PrintTemplateArgumentList(OS, Args, Policy); + printTemplateArgumentList(OS, Args, Policy); } spaceBeforePlaceHolder(OS); @@ -1113,8 +1128,7 @@ void TypePrinter::printTemplateSpecializationBefore( IncludeStrongLifetimeRAII Strong(Policy); T->getTemplateName().print(OS, Policy); - TemplateSpecializationType::PrintTemplateArgumentList( - OS, T->template_arguments(), Policy); + printTemplateArgumentList(OS, T->template_arguments(), Policy); spaceBeforePlaceHolder(OS); } void TypePrinter::printTemplateSpecializationAfter( @@ -1182,19 +1196,18 @@ void TypePrinter::printDependentNameAfter(const DependentNameType *T, void TypePrinter::printDependentTemplateSpecializationBefore( const DependentTemplateSpecializationType *T, raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); - + OS << TypeWithKeyword::getKeywordName(T->getKeyword()); if (T->getKeyword() != ETK_None) OS << " "; - + if (T->getQualifier()) - T->getQualifier()->print(OS, Policy); + T->getQualifier()->print(OS, Policy); OS << T->getIdentifier()->getName(); - TemplateSpecializationType::PrintTemplateArgumentList(OS, - T->template_arguments(), - Policy); + printTemplateArgumentList(OS, T->template_arguments(), Policy); spaceBeforePlaceHolder(OS); } + void TypePrinter::printDependentTemplateSpecializationAfter( const DependentTemplateSpecializationType *T, raw_ostream &OS) { } @@ -1304,7 +1317,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, default: llvm_unreachable("This attribute should have been handled already"); case AttributedType::attr_address_space: OS << "address_space("; - OS << T->getEquivalentType().getAddressSpace(); + // FIXME: printing the raw LangAS value is wrong. This should probably + // use the same code as Qualifiers::print() + OS << (unsigned)T->getEquivalentType().getAddressSpace(); OS << ')'; break; @@ -1503,41 +1518,39 @@ void TypePrinter::printObjCObjectPointerBefore(const ObjCObjectPointerType *T, OS << '*'; } } + void TypePrinter::printObjCObjectPointerAfter(const ObjCObjectPointerType *T, raw_ostream &OS) { } -void TemplateSpecializationType:: - PrintTemplateArgumentList(raw_ostream &OS, - const TemplateArgumentListInfo &Args, - const PrintingPolicy &Policy) { - return PrintTemplateArgumentList(OS, - Args.arguments(), - Policy); +static +const TemplateArgument &getArgument(const TemplateArgument &A) { return A; } + +static const TemplateArgument &getArgument(const TemplateArgumentLoc &A) { + return A.getArgument(); } -void TemplateSpecializationType::PrintTemplateArgumentList( - raw_ostream &OS, ArrayRef<TemplateArgument> Args, - const PrintingPolicy &Policy, bool SkipBrackets) { +template<typename TA> +static void printTo(raw_ostream &OS, ArrayRef<TA> Args, + const PrintingPolicy &Policy, bool SkipBrackets) { const char *Comma = Policy.MSVCFormatting ? "," : ", "; if (!SkipBrackets) OS << '<'; - bool needSpace = false; + bool NeedSpace = false; bool FirstArg = true; - for (const TemplateArgument &Arg : Args) { + for (const auto &Arg : Args) { // Print the argument into a string. SmallString<128> Buf; llvm::raw_svector_ostream ArgOS(Buf); - if (Arg.getKind() == TemplateArgument::Pack) { - if (Arg.pack_size() && !FirstArg) + const TemplateArgument &Argument = getArgument(Arg); + if (Argument.getKind() == TemplateArgument::Pack) { + if (Argument.pack_size() && !FirstArg) OS << Comma; - PrintTemplateArgumentList(ArgOS, - Arg.getPackAsArray(), - Policy, true); + printTo(ArgOS, Argument.getPackAsArray(), Policy, true); } else { if (!FirstArg) OS << Comma; - Arg.print(Policy, ArgOS); + Argument.print(Policy, ArgOS); } StringRef ArgString = ArgOS.str(); @@ -1549,65 +1562,36 @@ void TemplateSpecializationType::PrintTemplateArgumentList( OS << ArgString; - needSpace = (!ArgString.empty() && ArgString.back() == '>'); + NeedSpace = (!ArgString.empty() && ArgString.back() == '>'); FirstArg = false; } // If the last character of our string is '>', add another space to // keep the two '>''s separate tokens. We don't *have* to do this in // C++0x, but it's still good hygiene. - if (needSpace) + if (NeedSpace) OS << ' '; if (!SkipBrackets) OS << '>'; } -// Sadly, repeat all that with TemplateArgLoc. -void TemplateSpecializationType:: -PrintTemplateArgumentList(raw_ostream &OS, - ArrayRef<TemplateArgumentLoc> Args, - const PrintingPolicy &Policy) { - OS << '<'; - const char *Comma = Policy.MSVCFormatting ? "," : ", "; - - bool needSpace = false; - bool FirstArg = true; - for (const TemplateArgumentLoc &Arg : Args) { - if (!FirstArg) - OS << Comma; - - // Print the argument into a string. - SmallString<128> Buf; - llvm::raw_svector_ostream ArgOS(Buf); - if (Arg.getArgument().getKind() == TemplateArgument::Pack) { - PrintTemplateArgumentList(ArgOS, - Arg.getArgument().getPackAsArray(), - Policy, true); - } else { - Arg.getArgument().print(Policy, ArgOS); - } - StringRef ArgString = ArgOS.str(); - - // If this is the first argument and its string representation - // begins with the global scope specifier ('::foo'), add a space - // to avoid printing the diagraph '<:'. - if (FirstArg && !ArgString.empty() && ArgString[0] == ':') - OS << ' '; - - OS << ArgString; - - needSpace = (!ArgString.empty() && ArgString.back() == '>'); - FirstArg = false; - } +void clang::printTemplateArgumentList(raw_ostream &OS, + const TemplateArgumentListInfo &Args, + const PrintingPolicy &Policy) { + return printTo(OS, Args.arguments(), Policy, false); +} - // If the last character of our string is '>', add another space to - // keep the two '>''s separate tokens. We don't *have* to do this in - // C++0x, but it's still good hygiene. - if (needSpace) - OS << ' '; +void clang::printTemplateArgumentList(raw_ostream &OS, + ArrayRef<TemplateArgument> Args, + const PrintingPolicy &Policy) { + printTo(OS, Args, Policy, false); +} - OS << '>'; +void clang::printTemplateArgumentList(raw_ostream &OS, + ArrayRef<TemplateArgumentLoc> Args, + const PrintingPolicy &Policy) { + printTo(OS, Args, Policy, false); } std::string Qualifiers::getAsString() const { @@ -1629,7 +1613,7 @@ bool Qualifiers::isEmptyWhenPrinted(const PrintingPolicy &Policy) const { if (getCVRQualifiers()) return false; - if (getAddressSpace()) + if (getAddressSpace() != LangAS::Default) return false; if (getObjCGCAttr()) @@ -1660,17 +1644,21 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy, OS << "__unaligned"; addSpace = true; } - if (unsigned addrspace = getAddressSpace()) { - if (addSpace) - OS << ' '; - addSpace = true; - switch (addrspace) { + LangAS addrspace = getAddressSpace(); + if (addrspace != LangAS::Default) { + if (addrspace != LangAS::opencl_private) { + if (addSpace) + OS << ' '; + addSpace = true; + switch (addrspace) { case LangAS::opencl_global: OS << "__global"; break; case LangAS::opencl_local: OS << "__local"; break; + case LangAS::opencl_private: + break; case LangAS::opencl_constant: case LangAS::cuda_constant: OS << "__constant"; @@ -1685,10 +1673,10 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy, OS << "__shared"; break; default: - assert(addrspace >= LangAS::FirstTargetAddressSpace); OS << "__attribute__((address_space("; - OS << addrspace - LangAS::FirstTargetAddressSpace; + OS << toTargetAddressSpace(addrspace); OS << ")))"; + } } } if (Qualifiers::GC gc = getObjCGCAttr()) { diff --git a/lib/AST/VTTBuilder.cpp b/lib/AST/VTTBuilder.cpp index 53461ebbb812..b946f10105f4 100644 --- a/lib/AST/VTTBuilder.cpp +++ b/lib/AST/VTTBuilder.cpp @@ -1,4 +1,4 @@ -//===--- VTTBuilder.cpp - C++ VTT layout builder --------------------------===// +//===- VTTBuilder.cpp - C++ VTT layout builder ----------------------------===// // // The LLVM Compiler Infrastructure // @@ -14,12 +14,16 @@ #include "clang/AST/VTTBuilder.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/CXXInheritance.h" +#include "clang/AST/BaseSubobject.h" +#include "clang/AST/CharUnits.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/RecordLayout.h" -#include "clang/Basic/TargetInfo.h" -#include "llvm/Support/Format.h" -#include <algorithm> -#include <cstdio> +#include "clang/AST/Type.h" +#include "clang/Basic/LLVM.h" +#include "llvm/Support/Casting.h" +#include <cassert> +#include <cstdint> using namespace clang; @@ -28,9 +32,9 @@ using namespace clang; VTTBuilder::VTTBuilder(ASTContext &Ctx, const CXXRecordDecl *MostDerivedClass, bool GenerateDefinition) - : Ctx(Ctx), MostDerivedClass(MostDerivedClass), - MostDerivedClassLayout(Ctx.getASTRecordLayout(MostDerivedClass)), - GenerateDefinition(GenerateDefinition) { + : Ctx(Ctx), MostDerivedClass(MostDerivedClass), + MostDerivedClassLayout(Ctx.getASTRecordLayout(MostDerivedClass)), + GenerateDefinition(GenerateDefinition) { // Lay out this VTT. LayoutVTT(BaseSubobject(MostDerivedClass, CharUnits::Zero()), /*BaseIsVirtual=*/false); @@ -56,7 +60,7 @@ void VTTBuilder::AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex, void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) { const CXXRecordDecl *RD = Base.getBase(); - for (const auto &I : RD->bases()) { + for (const auto &I : RD->bases()) { // Don't layout virtual bases. if (I.isVirtual()) continue; diff --git a/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp index e60ae33f2e5c..347c516ef6a5 100644 --- a/lib/AST/VTableBuilder.cpp +++ b/lib/AST/VTableBuilder.cpp @@ -1079,9 +1079,7 @@ static void visitAllOverriddenMethods(const CXXMethodDecl *MD, VisitorTy &Visitor) { assert(MD->isVirtual() && "Method is not virtual!"); - for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), - E = MD->end_overridden_methods(); I != E; ++I) { - const CXXMethodDecl *OverriddenMD = *I; + for (const CXXMethodDecl *OverriddenMD : MD->overridden_methods()) { if (!Visitor(OverriddenMD)) continue; visitAllOverriddenMethods(OverriddenMD, Visitor); @@ -1329,11 +1327,8 @@ static bool OverridesIndirectMethodInBases( ItaniumVTableBuilder::PrimaryBasesSetVectorTy &Bases) { if (Bases.count(MD->getParent())) return true; - - for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), - E = MD->end_overridden_methods(); I != E; ++I) { - const CXXMethodDecl *OverriddenMD = *I; - + + for (const CXXMethodDecl *OverriddenMD : MD->overridden_methods()) { // Check "indirect overriders". if (OverridesIndirectMethodInBases(OverriddenMD, Bases)) return true; @@ -2963,6 +2958,9 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, CalculateVtordispAdjustment(FinalOverrider, ThisOffset, ThisAdjustmentOffset); + unsigned VBIndex = + LastVBase ? VTables.getVBTableIndex(MostDerivedClass, LastVBase) : 0; + if (OverriddenMD) { // If MD overrides anything in this vftable, we need to update the // entries. @@ -2975,6 +2973,8 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second; + VBIndex = OverriddenMethodInfo.VBTableIndex; + // Let's check if the overrider requires any return adjustments. // We must create a new slot if the MD's return type is not trivially // convertible to the OverriddenMD's one. @@ -2987,8 +2987,7 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, if (!ReturnAdjustingThunk) { // No return adjustment needed - just replace the overridden method info // with the current info. - MethodInfo MI(OverriddenMethodInfo.VBTableIndex, - OverriddenMethodInfo.VFTableIndex); + MethodInfo MI(VBIndex, OverriddenMethodInfo.VFTableIndex); MethodInfoMap.erase(OverriddenMDIterator); assert(!MethodInfoMap.count(MD) && @@ -3015,8 +3014,6 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, // If we got here, MD is a method not seen in any of the sub-bases or // it requires return adjustment. Insert the method info for this method. - unsigned VBIndex = - LastVBase ? VTables.getVBTableIndex(MostDerivedClass, LastVBase) : 0; MethodInfo MI(VBIndex, HasRTTIComponent ? Components.size() - 1 : Components.size(), ReturnAdjustingThunk); diff --git a/lib/ASTMatchers/ASTMatchFinder.cpp b/lib/ASTMatchers/ASTMatchFinder.cpp index 49b15ee68500..02aee4b46ddd 100644 --- a/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/lib/ASTMatchers/ASTMatchFinder.cpp @@ -734,7 +734,10 @@ private: BoundNodesTreeBuilder *Builder) { const Type *const CanonicalType = ActiveASTContext->getCanonicalType(TypeNode); - for (const TypedefNameDecl *Alias : TypeAliases.lookup(CanonicalType)) { + auto Aliases = TypeAliases.find(CanonicalType); + if (Aliases == TypeAliases.end()) + return false; + for (const TypedefNameDecl *Alias : Aliases->second) { BoundNodesTreeBuilder Result(*Builder); if (Matcher.matches(*Alias, this, &Result)) { *Builder = std::move(Result); diff --git a/lib/ASTMatchers/ASTMatchersInternal.cpp b/lib/ASTMatchers/ASTMatchersInternal.cpp index f0bfbf9e32d8..0bcdd8e32804 100644 --- a/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -1,4 +1,4 @@ -//===--- ASTMatchersInternal.cpp - Structural query framework -------------===// +//===- ASTMatchersInternal.cpp - Structural query framework ---------------===// // // The LLVM Compiler Infrastructure // @@ -11,11 +11,30 @@ // //===----------------------------------------------------------------------===// -#include "clang/ASTMatchers/ASTMatchers.h" #include "clang/ASTMatchers/ASTMatchersInternal.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTTypeTraits.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/PrettyPrinter.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <string> +#include <utility> +#include <vector> namespace clang { namespace ast_matchers { @@ -40,7 +59,6 @@ bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers); - void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) { if (Bindings.empty()) Bindings.push_back(BoundNodesMap()); @@ -51,7 +69,7 @@ void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) { namespace { -typedef bool (*VariadicOperatorFunction)( +using VariadicOperatorFunction = bool (*)( const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers); @@ -100,20 +118,22 @@ public: TrueMatcherImpl() { Retain(); // Reference count will never become zero. } + bool dynMatches(const ast_type_traits::DynTypedNode &, ASTMatchFinder *, BoundNodesTreeBuilder *) const override { return true; } }; -static llvm::ManagedStatic<TrueMatcherImpl> TrueMatcherInstance; -} // namespace +} // namespace + +static llvm::ManagedStatic<TrueMatcherImpl> TrueMatcherInstance; DynTypedMatcher DynTypedMatcher::constructVariadic( DynTypedMatcher::VariadicOperator Op, ast_type_traits::ASTNodeKind SupportedKind, std::vector<DynTypedMatcher> InnerMatchers) { - assert(InnerMatchers.size() > 0 && "Array must not be empty."); + assert(!InnerMatchers.empty() && "Array must not be empty."); assert(std::all_of(InnerMatchers.begin(), InnerMatchers.end(), [SupportedKind](const DynTypedMatcher &M) { return M.canConvertTo(SupportedKind); @@ -314,9 +334,7 @@ HasNameMatcher::HasNameMatcher(std::vector<std::string> N) #endif } -namespace { - -bool consumeNameSuffix(StringRef &FullName, StringRef Suffix) { +static bool consumeNameSuffix(StringRef &FullName, StringRef Suffix) { StringRef Name = FullName; if (!Name.endswith(Suffix)) return false; @@ -330,7 +348,8 @@ bool consumeNameSuffix(StringRef &FullName, StringRef Suffix) { return true; } -StringRef getNodeName(const NamedDecl &Node, llvm::SmallString<128> &Scratch) { +static StringRef getNodeName(const NamedDecl &Node, + llvm::SmallString<128> &Scratch) { // Simple name. if (Node.getIdentifier()) return Node.getName(); @@ -346,7 +365,8 @@ StringRef getNodeName(const NamedDecl &Node, llvm::SmallString<128> &Scratch) { return "(anonymous)"; } -StringRef getNodeName(const RecordDecl &Node, llvm::SmallString<128> &Scratch) { +static StringRef getNodeName(const RecordDecl &Node, + llvm::SmallString<128> &Scratch) { if (Node.getIdentifier()) { return Node.getName(); } @@ -354,11 +374,12 @@ StringRef getNodeName(const RecordDecl &Node, llvm::SmallString<128> &Scratch) { return ("(anonymous " + Node.getKindName() + ")").toStringRef(Scratch); } -StringRef getNodeName(const NamespaceDecl &Node, - llvm::SmallString<128> &Scratch) { +static StringRef getNodeName(const NamespaceDecl &Node, + llvm::SmallString<128> &Scratch) { return Node.isAnonymousNamespace() ? "(anonymous namespace)" : Node.getName(); } +namespace { class PatternSet { public: @@ -397,10 +418,11 @@ private: StringRef P; bool IsFullyQualified; }; + llvm::SmallVector<Pattern, 8> Patterns; }; -} // namespace +} // namespace bool HasNameMatcher::matchesNodeUnqualified(const NamedDecl &Node) const { assert(UseUnqualifiedMatch); @@ -504,5 +526,282 @@ bool HasNameMatcher::matchesNode(const NamedDecl &Node) const { } } // end namespace internal + +const internal::VariadicDynCastAllOfMatcher<Decl, TranslationUnitDecl> + translationUnitDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> typedefDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, TypedefNameDecl> + typedefNameDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasDecl> typeAliasDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasTemplateDecl> + typeAliasTemplateDecl; +const internal::VariadicAllOfMatcher<Decl> decl; +const internal::VariadicDynCastAllOfMatcher<Decl, LinkageSpecDecl> + linkageSpecDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, NamedDecl> namedDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, LabelDecl> labelDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceDecl> namespaceDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceAliasDecl> + namespaceAliasDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, RecordDecl> recordDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, CXXRecordDecl> cxxRecordDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, ClassTemplateDecl> + classTemplateDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, + ClassTemplateSpecializationDecl> + classTemplateSpecializationDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, DeclaratorDecl> + declaratorDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl> parmVarDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, AccessSpecDecl> + accessSpecDecl; +const internal::VariadicAllOfMatcher<CXXCtorInitializer> cxxCtorInitializer; +const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument; +const internal::VariadicAllOfMatcher<TemplateName> templateName; +const internal::VariadicDynCastAllOfMatcher<Decl, NonTypeTemplateParmDecl> + nonTypeTemplateParmDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, TemplateTypeParmDecl> + templateTypeParmDecl; +const internal::VariadicAllOfMatcher<QualType> qualType; +const internal::VariadicAllOfMatcher<Type> type; +const internal::VariadicAllOfMatcher<TypeLoc> typeLoc; +const internal::VariadicDynCastAllOfMatcher<Stmt, UnaryExprOrTypeTraitExpr> + unaryExprOrTypeTraitExpr; +const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, CXXConstructorDecl> + cxxConstructorDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, CXXDestructorDecl> + cxxDestructorDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, EnumConstantDecl> + enumConstantDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> cxxMethodDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl> + cxxConversionDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> varDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> functionDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, FunctionTemplateDecl> + functionTemplateDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, FriendDecl> friendDecl; +const internal::VariadicAllOfMatcher<Stmt> stmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, DeclStmt> declStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXMemberCallExpr> + cxxMemberCallExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCMessageExpr> + objcMessageExpr; +const internal::VariadicDynCastAllOfMatcher<Decl, ObjCInterfaceDecl> + objcInterfaceDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, ObjCImplementationDecl> + objcImplementationDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, ObjCProtocolDecl> + objcProtocolDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryDecl> + objcCategoryDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryImplDecl> + objcCategoryImplDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, ObjCMethodDecl> + objcMethodDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, ObjCIvarDecl> objcIvarDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, ObjCPropertyDecl> + objcPropertyDecl; +const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtThrowStmt> + objcThrowStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtTryStmt> objcTryStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtCatchStmt> + objcCatchStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtFinallyStmt> + objcFinallyStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, ExprWithCleanups> + exprWithCleanups; +const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXStdInitializerListExpr> + cxxStdInitializerListExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitValueInitExpr> + implicitValueInitExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, ParenListExpr> parenListExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, SubstNonTypeTemplateParmExpr> + substNonTypeTemplateParmExpr; +const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, UsingDirectiveDecl> + usingDirectiveDecl; +const internal::VariadicDynCastAllOfMatcher<Stmt, UnresolvedLookupExpr> + unresolvedLookupExpr; +const internal::VariadicDynCastAllOfMatcher<Decl, UnresolvedUsingValueDecl> + unresolvedUsingValueDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, UnresolvedUsingTypenameDecl> + unresolvedUsingTypenameDecl; +const internal::VariadicDynCastAllOfMatcher<Stmt, ParenExpr> parenExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXConstructExpr> + cxxConstructExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXUnresolvedConstructExpr> + cxxUnresolvedConstructExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr> cxxThisExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBindTemporaryExpr> + cxxBindTemporaryExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, MaterializeTemporaryExpr> + materializeTemporaryExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> cxxNewExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr> cxxDeleteExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, ArraySubscriptExpr> + arraySubscriptExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDefaultArgExpr> + cxxDefaultArgExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXOperatorCallExpr> + cxxOperatorCallExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr; +const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr> declRefExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, ForStmt> forStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXForRangeStmt> + cxxForRangeStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, WhileStmt> whileStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, BreakStmt> breakStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt> continueStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, ReturnStmt> returnStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, GotoStmt> gotoStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, LabelStmt> labelStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, AddrLabelExpr> addrLabelExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchStmt> switchStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchCase> switchCase; +const internal::VariadicDynCastAllOfMatcher<Stmt, CaseStmt> caseStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, DefaultStmt> defaultStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundStmt> compoundStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt> cxxCatchStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> cxxTryStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr> cxxThrowExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, NullStmt> nullStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, AsmStmt> asmStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBoolLiteralExpr> + cxxBoolLiteral; +const internal::VariadicDynCastAllOfMatcher<Stmt, StringLiteral> stringLiteral; +const internal::VariadicDynCastAllOfMatcher<Stmt, CharacterLiteral> + characterLiteral; +const internal::VariadicDynCastAllOfMatcher<Stmt, IntegerLiteral> + integerLiteral; +const internal::VariadicDynCastAllOfMatcher<Stmt, FloatingLiteral> floatLiteral; +const internal::VariadicDynCastAllOfMatcher<Stmt, UserDefinedLiteral> + userDefinedLiteral; +const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundLiteralExpr> + compoundLiteralExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNullPtrLiteralExpr> + cxxNullPtrLiteralExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, GNUNullExpr> gnuNullExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, AtomicExpr> atomicExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, StmtExpr> stmtExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, BinaryOperator> + binaryOperator; +const internal::VariadicDynCastAllOfMatcher<Stmt, UnaryOperator> unaryOperator; +const internal::VariadicDynCastAllOfMatcher<Stmt, ConditionalOperator> + conditionalOperator; +const internal::VariadicDynCastAllOfMatcher<Stmt, BinaryConditionalOperator> + binaryConditionalOperator; +const internal::VariadicDynCastAllOfMatcher<Stmt, OpaqueValueExpr> + opaqueValueExpr; +const internal::VariadicDynCastAllOfMatcher<Decl, StaticAssertDecl> + staticAssertDecl; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXReinterpretCastExpr> + cxxReinterpretCastExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXStaticCastExpr> + cxxStaticCastExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDynamicCastExpr> + cxxDynamicCastExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXConstCastExpr> + cxxConstCastExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CStyleCastExpr> + cStyleCastExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, ExplicitCastExpr> + explicitCastExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitCastExpr> + implicitCastExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CastExpr> castExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXFunctionalCastExpr> + cxxFunctionalCastExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTemporaryObjectExpr> + cxxTemporaryObjectExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, PredefinedExpr> + predefinedExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, DesignatedInitExpr> + designatedInitExpr; +const internal::VariadicOperatorMatcherFunc< + 2, std::numeric_limits<unsigned>::max()> + eachOf = {internal::DynTypedMatcher::VO_EachOf}; +const internal::VariadicOperatorMatcherFunc< + 2, std::numeric_limits<unsigned>::max()> + anyOf = {internal::DynTypedMatcher::VO_AnyOf}; +const internal::VariadicOperatorMatcherFunc< + 2, std::numeric_limits<unsigned>::max()> + allOf = {internal::DynTypedMatcher::VO_AllOf}; +const internal::VariadicFunction<internal::Matcher<NamedDecl>, StringRef, + internal::hasAnyNameFunc> + hasAnyName = {}; +const internal::ArgumentAdaptingMatcherFunc<internal::HasMatcher> has = {}; +const internal::ArgumentAdaptingMatcherFunc<internal::HasDescendantMatcher> + hasDescendant = {}; +const internal::ArgumentAdaptingMatcherFunc<internal::ForEachMatcher> forEach = + {}; +const internal::ArgumentAdaptingMatcherFunc<internal::ForEachDescendantMatcher> + forEachDescendant = {}; +const internal::ArgumentAdaptingMatcherFunc< + internal::HasParentMatcher, + internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>, + internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>> + hasParent = {}; +const internal::ArgumentAdaptingMatcherFunc< + internal::HasAncestorMatcher, + internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>, + internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>> + hasAncestor = {}; +const internal::VariadicOperatorMatcherFunc<1, 1> unless = { + internal::DynTypedMatcher::VO_UnaryNot}; +const internal::VariadicAllOfMatcher<NestedNameSpecifier> nestedNameSpecifier; +const internal::VariadicAllOfMatcher<NestedNameSpecifierLoc> + nestedNameSpecifierLoc; +const internal::VariadicDynCastAllOfMatcher<Stmt, CUDAKernelCallExpr> + cudaKernelCallExpr; +const AstTypeMatcher<BuiltinType> builtinType; +const AstTypeMatcher<ArrayType> arrayType; +const AstTypeMatcher<ComplexType> complexType; +const AstTypeMatcher<ConstantArrayType> constantArrayType; +const AstTypeMatcher<DependentSizedArrayType> dependentSizedArrayType; +const AstTypeMatcher<IncompleteArrayType> incompleteArrayType; +const AstTypeMatcher<VariableArrayType> variableArrayType; +const AstTypeMatcher<AtomicType> atomicType; +const AstTypeMatcher<AutoType> autoType; +const AstTypeMatcher<FunctionType> functionType; +const AstTypeMatcher<FunctionProtoType> functionProtoType; +const AstTypeMatcher<ParenType> parenType; +const AstTypeMatcher<BlockPointerType> blockPointerType; +const AstTypeMatcher<MemberPointerType> memberPointerType; +const AstTypeMatcher<PointerType> pointerType; +const AstTypeMatcher<ObjCObjectPointerType> objcObjectPointerType; +const AstTypeMatcher<ReferenceType> referenceType; +const AstTypeMatcher<LValueReferenceType> lValueReferenceType; +const AstTypeMatcher<RValueReferenceType> rValueReferenceType; +const AstTypeMatcher<TypedefType> typedefType; +const AstTypeMatcher<EnumType> enumType; +const AstTypeMatcher<TemplateSpecializationType> templateSpecializationType; +const AstTypeMatcher<UnaryTransformType> unaryTransformType; +const AstTypeMatcher<RecordType> recordType; +const AstTypeMatcher<TagType> tagType; +const AstTypeMatcher<ElaboratedType> elaboratedType; +const AstTypeMatcher<SubstTemplateTypeParmType> substTemplateTypeParmType; +const AstTypeMatcher<TemplateTypeParmType> templateTypeParmType; +const AstTypeMatcher<InjectedClassNameType> injectedClassNameType; +const AstTypeMatcher<DecayedType> decayedType; +AST_TYPELOC_TRAVERSE_MATCHER_DEF(hasElementType, + AST_POLYMORPHIC_SUPPORTED_TYPES(ArrayType, + ComplexType)); +AST_TYPELOC_TRAVERSE_MATCHER_DEF(hasValueType, + AST_POLYMORPHIC_SUPPORTED_TYPES(AtomicType)); +AST_TYPELOC_TRAVERSE_MATCHER_DEF( + pointee, + AST_POLYMORPHIC_SUPPORTED_TYPES(BlockPointerType, MemberPointerType, + PointerType, ReferenceType)); + } // end namespace ast_matchers } // end namespace clang diff --git a/lib/ASTMatchers/Dynamic/Marshallers.h b/lib/ASTMatchers/Dynamic/Marshallers.h index c557ff162691..af90e2c7eca1 100644 --- a/lib/ASTMatchers/Dynamic/Marshallers.h +++ b/lib/ASTMatchers/Dynamic/Marshallers.h @@ -1,4 +1,4 @@ -//===--- Marshallers.h - Generic matcher function marshallers ---*- C++ -*-===// +//===- Marshallers.h - Generic matcher function marshallers -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,7 +6,7 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Functions templates and classes to wrap matcher construct functions. /// @@ -14,18 +14,33 @@ /// marshalling layer on top of matcher construct functions. /// These are used by the registry to export all marshaller constructors with /// the same generic interface. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_LIB_ASTMATCHERS_DYNAMIC_MARSHALLERS_H #define LLVM_CLANG_LIB_ASTMATCHERS_DYNAMIC_MARSHALLERS_H -#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/AST/ASTTypeTraits.h" +#include "clang/AST/OperationKinds.h" +#include "clang/ASTMatchers/ASTMatchersInternal.h" #include "clang/ASTMatchers/Dynamic/Diagnostics.h" #include "clang/ASTMatchers/Dynamic/VariantValue.h" +#include "clang/Basic/AttrKinds.h" #include "clang/Basic/LLVM.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" +#include <cassert> +#include <cstddef> +#include <iterator> +#include <limits> +#include <memory> #include <string> +#include <utility> +#include <vector> namespace clang { namespace ast_matchers { @@ -41,9 +56,11 @@ template <class T> struct ArgTypeTraits<const T &> : public ArgTypeTraits<T> { template <> struct ArgTypeTraits<std::string> { static bool is(const VariantValue &Value) { return Value.isString(); } + static const std::string &get(const VariantValue &Value) { return Value.getString(); } + static ArgKind getKind() { return ArgKind(ArgKind::AK_String); } @@ -53,13 +70,15 @@ template <> struct ArgTypeTraits<StringRef> : public ArgTypeTraits<std::string> { }; -template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T> > { +template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T>> { static bool is(const VariantValue &Value) { return Value.isMatcher() && Value.getMatcher().hasTypedMatcher<T>(); } + static ast_matchers::internal::Matcher<T> get(const VariantValue &Value) { return Value.getMatcher().getTypedMatcher<T>(); } + static ArgKind getKind() { return ArgKind(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()); } @@ -67,9 +86,11 @@ template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T> > { template <> struct ArgTypeTraits<bool> { static bool is(const VariantValue &Value) { return Value.isBoolean(); } + static bool get(const VariantValue &Value) { return Value.getBoolean(); } + static ArgKind getKind() { return ArgKind(ArgKind::AK_Boolean); } @@ -77,9 +98,11 @@ template <> struct ArgTypeTraits<bool> { template <> struct ArgTypeTraits<double> { static bool is(const VariantValue &Value) { return Value.isDouble(); } + static double get(const VariantValue &Value) { return Value.getDouble(); } + static ArgKind getKind() { return ArgKind(ArgKind::AK_Double); } @@ -87,9 +110,11 @@ template <> struct ArgTypeTraits<double> { template <> struct ArgTypeTraits<unsigned> { static bool is(const VariantValue &Value) { return Value.isUnsigned(); } + static unsigned get(const VariantValue &Value) { return Value.getUnsigned(); } + static ArgKind getKind() { return ArgKind(ArgKind::AK_Unsigned); } @@ -97,42 +122,45 @@ template <> struct ArgTypeTraits<unsigned> { template <> struct ArgTypeTraits<attr::Kind> { private: - static attr::Kind getAttrKind(llvm::StringRef AttrKind) { - return llvm::StringSwitch<attr::Kind>(AttrKind) + static Optional<attr::Kind> getAttrKind(llvm::StringRef AttrKind) { + return llvm::StringSwitch<Optional<attr::Kind>>(AttrKind) #define ATTR(X) .Case("attr::" #X, attr:: X) #include "clang/Basic/AttrList.inc" - .Default(attr::Kind(-1)); + .Default(llvm::None); } + public: static bool is(const VariantValue &Value) { - return Value.isString() && - getAttrKind(Value.getString()) != attr::Kind(-1); + return Value.isString() && getAttrKind(Value.getString()); } + static attr::Kind get(const VariantValue &Value) { - return getAttrKind(Value.getString()); + return *getAttrKind(Value.getString()); } + static ArgKind getKind() { return ArgKind(ArgKind::AK_String); } }; -template <> struct ArgTypeTraits<clang::CastKind> { +template <> struct ArgTypeTraits<CastKind> { private: - static clang::CastKind getCastKind(llvm::StringRef AttrKind) { - return llvm::StringSwitch<clang::CastKind>(AttrKind) + static Optional<CastKind> getCastKind(llvm::StringRef AttrKind) { + return llvm::StringSwitch<Optional<CastKind>>(AttrKind) #define CAST_OPERATION(Name) .Case( #Name, CK_##Name) #include "clang/AST/OperationKinds.def" - .Default(CK_Invalid); + .Default(llvm::None); } public: static bool is(const VariantValue &Value) { - return Value.isString() && - getCastKind(Value.getString()) != CK_Invalid; + return Value.isString() && getCastKind(Value.getString()); } - static clang::CastKind get(const VariantValue &Value) { - return getCastKind(Value.getString()); + + static CastKind get(const VariantValue &Value) { + return *getCastKind(Value.getString()); } + static ArgKind getKind() { return ArgKind(ArgKind::AK_String); } @@ -144,7 +172,8 @@ public: /// arguments, and various other methods for type introspection. class MatcherDescriptor { public: - virtual ~MatcherDescriptor() {} + virtual ~MatcherDescriptor() = default; + virtual VariantMatcher create(SourceRange NameRange, ArrayRef<ParserValue> Args, Diagnostics *Error) const = 0; @@ -201,11 +230,11 @@ inline bool isRetKindConvertibleTo( /// their types, unpacking them and calling the underlying function. class FixedArgCountMatcherDescriptor : public MatcherDescriptor { public: - typedef VariantMatcher (*MarshallerType)(void (*Func)(), - StringRef MatcherName, - SourceRange NameRange, - ArrayRef<ParserValue> Args, - Diagnostics *Error); + using MarshallerType = VariantMatcher (*)(void (*Func)(), + StringRef MatcherName, + SourceRange NameRange, + ArrayRef<ParserValue> Args, + Diagnostics *Error); /// \param Marshaller Function to unpack the arguments and call \c Func /// \param Func Matcher construct function. This is the function that @@ -229,10 +258,12 @@ public: bool isVariadic() const override { return false; } unsigned getNumArgs() const override { return ArgKinds.size(); } + void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo, std::vector<ArgKind> &Kinds) const override { Kinds.push_back(ArgKinds[ArgNo]); } + bool isConvertibleTo( ast_type_traits::ASTNodeKind Kind, unsigned *Specificity, ast_type_traits::ASTNodeKind *LeastDerivedKind) const override { @@ -303,14 +334,14 @@ struct BuildReturnTypeVector { }; template <typename T> -struct BuildReturnTypeVector<ast_matchers::internal::Matcher<T> > { +struct BuildReturnTypeVector<ast_matchers::internal::Matcher<T>> { static void build(std::vector<ast_type_traits::ASTNodeKind> &RetTypes) { RetTypes.push_back(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()); } }; template <typename T> -struct BuildReturnTypeVector<ast_matchers::internal::BindableMatcher<T> > { +struct BuildReturnTypeVector<ast_matchers::internal::BindableMatcher<T>> { static void build(std::vector<ast_type_traits::ASTNodeKind> &RetTypes) { RetTypes.push_back(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()); } @@ -326,7 +357,8 @@ variadicMatcherDescriptor(StringRef MatcherName, SourceRange NameRange, bool HasError = false; for (size_t i = 0, e = Args.size(); i != e; ++i) { - typedef ArgTypeTraits<ArgT> ArgTraits; + using ArgTraits = ArgTypeTraits<ArgT>; + const ParserValue &Arg = Args[i]; const VariantValue &Value = Arg.Value; if (!ArgTraits::is(Value)) { @@ -360,10 +392,10 @@ variadicMatcherDescriptor(StringRef MatcherName, SourceRange NameRange, /// object file. class VariadicFuncMatcherDescriptor : public MatcherDescriptor { public: - typedef VariantMatcher (*RunFunc)(StringRef MatcherName, - SourceRange NameRange, - ArrayRef<ParserValue> Args, - Diagnostics *Error); + using RunFunc = VariantMatcher (*)(StringRef MatcherName, + SourceRange NameRange, + ArrayRef<ParserValue> Args, + Diagnostics *Error); template <typename ResultT, typename ArgT, ResultT (*F)(ArrayRef<const ArgT *>)> @@ -384,10 +416,12 @@ public: bool isVariadic() const override { return true; } unsigned getNumArgs() const override { return 0; } + void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo, std::vector<ArgKind> &Kinds) const override { Kinds.push_back(ArgsKind); } + bool isConvertibleTo( ast_type_traits::ASTNodeKind Kind, unsigned *Specificity, ast_type_traits::ASTNodeKind *LeastDerivedKind) const override { @@ -458,7 +492,7 @@ static VariantMatcher matcherMarshall0(void (*Func)(), StringRef MatcherName, SourceRange NameRange, ArrayRef<ParserValue> Args, Diagnostics *Error) { - typedef ReturnType (*FuncType)(); + using FuncType = ReturnType (*)(); CHECK_ARG_COUNT(0); return outvalueToVariantMatcher(reinterpret_cast<FuncType>(Func)()); } @@ -469,7 +503,7 @@ static VariantMatcher matcherMarshall1(void (*Func)(), StringRef MatcherName, SourceRange NameRange, ArrayRef<ParserValue> Args, Diagnostics *Error) { - typedef ReturnType (*FuncType)(ArgType1); + using FuncType = ReturnType (*)(ArgType1); CHECK_ARG_COUNT(1); CHECK_ARG_TYPE(0, ArgType1); return outvalueToVariantMatcher(reinterpret_cast<FuncType>(Func)( @@ -482,7 +516,7 @@ static VariantMatcher matcherMarshall2(void (*Func)(), StringRef MatcherName, SourceRange NameRange, ArrayRef<ParserValue> Args, Diagnostics *Error) { - typedef ReturnType (*FuncType)(ArgType1, ArgType2); + using FuncType = ReturnType (*)(ArgType1, ArgType2); CHECK_ARG_COUNT(2); CHECK_ARG_TYPE(0, ArgType1); CHECK_ARG_TYPE(1, ArgType2); @@ -507,8 +541,8 @@ public: } private: - typedef ast_matchers::internal::ArgumentAdaptingMatcherFunc< - ArgumentAdapterT, FromTypes, ToTypes> AdaptativeFunc; + using AdaptativeFunc = ast_matchers::internal::ArgumentAdaptingMatcherFunc< + ArgumentAdapterT, FromTypes, ToTypes>; /// \brief End case for the recursion static void collect(ast_matchers::internal::EmptyTypeList) {} @@ -534,7 +568,7 @@ public: : Overloads(std::make_move_iterator(Callbacks.begin()), std::make_move_iterator(Callbacks.end())) {} - ~OverloadedMatcherDescriptor() override {} + ~OverloadedMatcherDescriptor() override = default; VariantMatcher create(SourceRange NameRange, ArrayRef<ParserValue> Args, @@ -604,7 +638,8 @@ private: /// \brief Variadic operator marshaller function. class VariadicOperatorMatcherDescriptor : public MatcherDescriptor { public: - typedef DynTypedMatcher::VariadicOperator VarOp; + using VarOp = DynTypedMatcher::VariadicOperator; + VariadicOperatorMatcherDescriptor(unsigned MinCount, unsigned MaxCount, VarOp Op, StringRef MatcherName) : MinCount(MinCount), MaxCount(MaxCount), Op(Op), @@ -615,7 +650,9 @@ public: Diagnostics *Error) const override { if (Args.size() < MinCount || MaxCount < Args.size()) { const std::string MaxStr = - (MaxCount == UINT_MAX ? "" : Twine(MaxCount)).str(); + (MaxCount == std::numeric_limits<unsigned>::max() ? "" + : Twine(MaxCount)) + .str(); Error->addError(NameRange, Error->ET_RegistryWrongArgCount) << ("(" + Twine(MinCount) + ", " + MaxStr + ")") << Args.size(); return VariantMatcher(); @@ -637,10 +674,12 @@ public: bool isVariadic() const override { return true; } unsigned getNumArgs() const override { return 0; } + void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo, std::vector<ArgKind> &Kinds) const override { Kinds.push_back(ThisKind); } + bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity, ast_type_traits::ASTNodeKind *LeastDerivedKind) const override { if (Specificity) @@ -649,6 +688,7 @@ public: *LeastDerivedKind = Kind; return true; } + bool isPolymorphic() const override { return true; } private: diff --git a/lib/ASTMatchers/Dynamic/Parser.cpp b/lib/ASTMatchers/Dynamic/Parser.cpp index f5bd29668995..89e1a2695860 100644 --- a/lib/ASTMatchers/Dynamic/Parser.cpp +++ b/lib/ASTMatchers/Dynamic/Parser.cpp @@ -1,4 +1,4 @@ -//===--- Parser.cpp - Matcher expression parser -----*- C++ -*-===// +//===- Parser.cpp - Matcher expression parser -----------------------------===// // // The LLVM Compiler Infrastructure // @@ -13,11 +13,21 @@ //===----------------------------------------------------------------------===// #include "clang/ASTMatchers/Dynamic/Parser.h" +#include "clang/ASTMatchers/ASTMatchersInternal.h" +#include "clang/ASTMatchers/Dynamic/Diagnostics.h" #include "clang/ASTMatchers/Dynamic/Registry.h" #include "clang/Basic/CharInfo.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" +#include <algorithm> +#include <cassert> +#include <cerrno> +#include <cstddef> +#include <cstdlib> #include <string> +#include <utility> #include <vector> namespace clang { @@ -43,10 +53,10 @@ struct Parser::TokenInfo { /// \brief Some known identifiers. static const char* const ID_Bind; - TokenInfo() : Text(), Kind(TK_Eof), Range(), Value() {} + TokenInfo() = default; StringRef Text; - TokenKind Kind; + TokenKind Kind = TK_Eof; SourceRange Range; VariantValue Value; }; @@ -57,14 +67,13 @@ const char* const Parser::TokenInfo::ID_Bind = "bind"; class Parser::CodeTokenizer { public: explicit CodeTokenizer(StringRef MatcherCode, Diagnostics *Error) - : Code(MatcherCode), StartOfLine(MatcherCode), Line(1), Error(Error), - CodeCompletionLocation(nullptr) { + : Code(MatcherCode), StartOfLine(MatcherCode), Error(Error) { NextToken = getNextToken(); } CodeTokenizer(StringRef MatcherCode, Diagnostics *Error, unsigned CodeCompletionOffset) - : Code(MatcherCode), StartOfLine(MatcherCode), Line(1), Error(Error), + : Code(MatcherCode), StartOfLine(MatcherCode), Error(Error), CodeCompletionLocation(MatcherCode.data() + CodeCompletionOffset) { NextToken = getNextToken(); } @@ -138,7 +147,7 @@ private: if (isAlphanumeric(Code[0])) { // Parse an identifier size_t TokenLength = 1; - while (1) { + while (true) { // A code completion location in/immediately after an identifier will // cause the portion of the identifier before the code completion // location to become a code completion token. @@ -283,22 +292,22 @@ private: StringRef Code; StringRef StartOfLine; - unsigned Line; + unsigned Line = 1; Diagnostics *Error; TokenInfo NextToken; - const char *CodeCompletionLocation; + const char *CodeCompletionLocation = nullptr; }; -Parser::Sema::~Sema() {} +Parser::Sema::~Sema() = default; std::vector<ArgKind> Parser::Sema::getAcceptedCompletionTypes( llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context) { - return std::vector<ArgKind>(); + return {}; } std::vector<MatcherCompletion> Parser::Sema::getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes) { - return std::vector<MatcherCompletion>(); + return {}; } struct Parser::ScopedContextEntry { @@ -384,7 +393,7 @@ bool Parser::parseMatcherExpressionImpl(const TokenInfo &NameToken, EndToken = Tokenizer->consumeNextToken(); break; } - if (Args.size() > 0) { + if (!Args.empty()) { // We must find a , token to continue. const TokenInfo CommaToken = Tokenizer->consumeNextToken(); if (CommaToken.Kind != TokenInfo::TK_Comma) { @@ -558,7 +567,7 @@ Parser::Parser(CodeTokenizer *Tokenizer, Sema *S, : Tokenizer(Tokenizer), S(S ? S : &*DefaultRegistrySema), NamedValues(NamedValues), Error(Error) {} -Parser::RegistrySema::~RegistrySema() {} +Parser::RegistrySema::~RegistrySema() = default; llvm::Optional<MatcherCtor> Parser::RegistrySema::lookupMatcherCtor(StringRef MatcherName) { @@ -640,6 +649,6 @@ Parser::parseMatcherExpression(StringRef Code, Sema *S, return Result; } -} // namespace dynamic -} // namespace ast_matchers -} // namespace clang +} // namespace dynamic +} // namespace ast_matchers +} // namespace clang diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp index 031ceb320306..2b7bb7a2120d 100644 --- a/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/lib/ASTMatchers/Dynamic/Registry.cpp @@ -1,37 +1,49 @@ -//===--- Registry.cpp - Matcher registry -------------------------===// +//===- Registry.cpp - Matcher registry ------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // -//===------------------------------------------------------------===// -/// +//===----------------------------------------------------------------------===// +// /// \file /// \brief Registry map populated at static initialization time. -/// -//===------------------------------------------------------------===// +// +//===----------------------------------------------------------------------===// #include "clang/ASTMatchers/Dynamic/Registry.h" #include "Marshallers.h" +#include "clang/AST/ASTTypeTraits.h" #include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/ASTMatchers/Dynamic/Diagnostics.h" +#include "clang/ASTMatchers/Dynamic/VariantValue.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <iterator> +#include <memory> #include <set> +#include <string> #include <utility> +#include <vector> using namespace clang::ast_type_traits; namespace clang { namespace ast_matchers { namespace dynamic { + namespace { using internal::MatcherDescriptor; -typedef llvm::StringMap<std::unique_ptr<const MatcherDescriptor>> ConstructorMap; +using ConstructorMap = llvm::StringMap<std::unique_ptr<const MatcherDescriptor>>; + class RegistryMaps { public: RegistryMaps(); @@ -46,6 +58,8 @@ private: ConstructorMap Constructors; }; +} // namespace + void RegistryMaps::registerMatcher( StringRef MatcherName, std::unique_ptr<MatcherDescriptor> Callback) { assert(Constructors.find(MatcherName) == Constructors.end()); @@ -74,7 +88,7 @@ void RegistryMaps::registerMatcher( MATCHER_OVERLOAD_ENTRY(name, 0), \ MATCHER_OVERLOAD_ENTRY(name, 1)}; \ REGISTER_MATCHER_OVERLOAD(name); \ - } while (0) + } while (false) /// \brief Generate a registry map with all the known matchers. RegistryMaps::RegistryMaps() { @@ -196,6 +210,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(forEachArgumentWithParam); REGISTER_MATCHER(forEachConstructorInitializer); REGISTER_MATCHER(forEachDescendant); + REGISTER_MATCHER(forEachOverridden); REGISTER_MATCHER(forEachSwitchCase); REGISTER_MATCHER(forField); REGISTER_MATCHER(forFunction); @@ -219,6 +234,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasAnyUsingShadowDecl); REGISTER_MATCHER(hasArgument); REGISTER_MATCHER(hasArgumentOfType); + REGISTER_MATCHER(hasArraySize); REGISTER_MATCHER(hasAttr); REGISTER_MATCHER(hasAutomaticStorageDuration); REGISTER_MATCHER(hasBase); @@ -233,6 +249,8 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasDeclaration); REGISTER_MATCHER(hasDeclContext); REGISTER_MATCHER(hasDeducedType); + REGISTER_MATCHER(hasDefaultArgument); + REGISTER_MATCHER(hasDefinition); REGISTER_MATCHER(hasDescendant); REGISTER_MATCHER(hasDestinationType); REGISTER_MATCHER(hasDynamicExceptionSpec); @@ -301,6 +319,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(isAnonymous); REGISTER_MATCHER(isAnyCharacter); REGISTER_MATCHER(isAnyPointer); + REGISTER_MATCHER(isArray); REGISTER_MATCHER(isArrow); REGISTER_MATCHER(isBaseInitializer); REGISTER_MATCHER(isBitField); @@ -355,6 +374,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(labelDecl); REGISTER_MATCHER(labelStmt); REGISTER_MATCHER(lambdaExpr); + REGISTER_MATCHER(linkageSpecDecl); REGISTER_MATCHER(lValueReferenceType); REGISTER_MATCHER(matchesName); REGISTER_MATCHER(matchesSelector); @@ -372,7 +392,11 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(nullStmt); REGISTER_MATCHER(numSelectorArgs); REGISTER_MATCHER(ofClass); + REGISTER_MATCHER(objcCatchStmt); REGISTER_MATCHER(objcCategoryDecl); + REGISTER_MATCHER(objcCategoryImplDecl); + REGISTER_MATCHER(objcFinallyStmt); + REGISTER_MATCHER(objcImplementationDecl); REGISTER_MATCHER(objcInterfaceDecl); REGISTER_MATCHER(objcIvarDecl); REGISTER_MATCHER(objcMessageExpr); @@ -380,6 +404,8 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(objcObjectPointerType); REGISTER_MATCHER(objcPropertyDecl); REGISTER_MATCHER(objcProtocolDecl); + REGISTER_MATCHER(objcThrowStmt); + REGISTER_MATCHER(objcTryStmt); REGISTER_MATCHER(on); REGISTER_MATCHER(onImplicitObjectArgument); REGISTER_MATCHER(opaqueValueExpr); @@ -450,12 +476,10 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(withInitializer); } -RegistryMaps::~RegistryMaps() {} +RegistryMaps::~RegistryMaps() = default; static llvm::ManagedStatic<RegistryMaps> RegistryData; -} // anonymous namespace - // static llvm::Optional<MatcherCtor> Registry::lookupMatcherCtor(StringRef MatcherName) { auto it = RegistryData->constructors().find(MatcherName); @@ -464,10 +488,8 @@ llvm::Optional<MatcherCtor> Registry::lookupMatcherCtor(StringRef MatcherName) { : it->second.get(); } -namespace { - -llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, - const std::set<ASTNodeKind> &KS) { +static llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const std::set<ASTNodeKind> &KS) { unsigned Count = 0; for (std::set<ASTNodeKind>::const_iterator I = KS.begin(), E = KS.end(); I != E; ++I) { @@ -482,8 +504,6 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, return OS; } -} // namespace - std::vector<ArgKind> Registry::getAcceptedCompletionTypes( ArrayRef<std::pair<MatcherCtor, unsigned>> Context) { ASTNodeKind InitialTypes[] = { @@ -593,7 +613,6 @@ Registry::getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes) { return Completions; } -// static VariantMatcher Registry::constructMatcher(MatcherCtor Ctor, SourceRange NameRange, ArrayRef<ParserValue> Args, @@ -601,7 +620,6 @@ VariantMatcher Registry::constructMatcher(MatcherCtor Ctor, return Ctor->create(NameRange, Args, Error); } -// static VariantMatcher Registry::constructBoundMatcher(MatcherCtor Ctor, SourceRange NameRange, StringRef BindID, @@ -621,6 +639,6 @@ VariantMatcher Registry::constructBoundMatcher(MatcherCtor Ctor, return VariantMatcher(); } -} // namespace dynamic -} // namespace ast_matchers -} // namespace clang +} // namespace dynamic +} // namespace ast_matchers +} // namespace clang diff --git a/lib/Analysis/AnalysisDeclContext.cpp b/lib/Analysis/AnalysisDeclContext.cpp index ec15f34fb231..181edff0a03f 100644 --- a/lib/Analysis/AnalysisDeclContext.cpp +++ b/lib/Analysis/AnalysisDeclContext.cpp @@ -12,8 +12,7 @@ // //===----------------------------------------------------------------------===// -#include "clang/Analysis/AnalysisContext.h" -#include "BodyFarm.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" @@ -23,6 +22,7 @@ #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" #include "clang/Analysis/Analyses/LiveVariables.h" #include "clang/Analysis/Analyses/PseudoConstantAnalysis.h" +#include "clang/Analysis/BodyFarm.h" #include "clang/Analysis/CFG.h" #include "clang/Analysis/CFGStmtMap.h" #include "clang/Analysis/Support/BumpVector.h" @@ -63,33 +63,25 @@ AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *Mgr, cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs; } -AnalysisDeclContextManager::AnalysisDeclContextManager(bool useUnoptimizedCFG, - bool addImplicitDtors, - bool addInitializers, - bool addTemporaryDtors, - bool addLifetime, - bool synthesizeBodies, - bool addStaticInitBranch, - bool addCXXNewAllocator, - CodeInjector *injector) - : Injector(injector), SynthesizeBodies(synthesizeBodies) -{ +AnalysisDeclContextManager::AnalysisDeclContextManager( + ASTContext &ASTCtx, bool useUnoptimizedCFG, bool addImplicitDtors, + bool addInitializers, bool addTemporaryDtors, bool addLifetime, + bool addLoopExit, bool synthesizeBodies, bool addStaticInitBranch, + bool addCXXNewAllocator, CodeInjector *injector) + : Injector(injector), FunctionBodyFarm(ASTCtx, injector), + SynthesizeBodies(synthesizeBodies) { cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG; cfgBuildOptions.AddImplicitDtors = addImplicitDtors; cfgBuildOptions.AddInitializers = addInitializers; cfgBuildOptions.AddTemporaryDtors = addTemporaryDtors; cfgBuildOptions.AddLifetime = addLifetime; + cfgBuildOptions.AddLoopExit = addLoopExit; cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch; cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator; } void AnalysisDeclContextManager::clear() { Contexts.clear(); } -static BodyFarm &getBodyFarm(ASTContext &C, CodeInjector *injector = nullptr) { - static BodyFarm *BF = new BodyFarm(C, injector); - return *BF; -} - Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const { IsAutosynthesized = false; if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { @@ -97,8 +89,7 @@ Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const { if (auto *CoroBody = dyn_cast_or_null<CoroutineBodyStmt>(Body)) Body = CoroBody->getBody(); if (Manager && Manager->synthesizeBodies()) { - Stmt *SynthesizedBody = - getBodyFarm(getASTContext(), Manager->Injector.get()).getBody(FD); + Stmt *SynthesizedBody = Manager->getBodyFarm().getBody(FD); if (SynthesizedBody) { Body = SynthesizedBody; IsAutosynthesized = true; @@ -109,8 +100,7 @@ Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const { else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { Stmt *Body = MD->getBody(); if (Manager && Manager->synthesizeBodies()) { - Stmt *SynthesizedBody = - getBodyFarm(getASTContext(), Manager->Injector.get()).getBody(MD); + Stmt *SynthesizedBody = Manager->getBodyFarm().getBody(MD); if (SynthesizedBody) { Body = SynthesizedBody; IsAutosynthesized = true; @@ -315,6 +305,8 @@ AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) { return AC.get(); } +BodyFarm &AnalysisDeclContextManager::getBodyFarm() { return FunctionBodyFarm; } + const StackFrameContext * AnalysisDeclContext::getStackFrame(LocationContext const *Parent, const Stmt *S, const CFGBlock *Blk, unsigned Idx) { @@ -608,8 +600,6 @@ AnalysisDeclContext::~AnalysisDeclContext() { } } -AnalysisDeclContextManager::~AnalysisDeclContextManager() {} - LocationContext::~LocationContext() {} LocationContextManager::~LocationContextManager() { diff --git a/lib/Analysis/BodyFarm.cpp b/lib/Analysis/BodyFarm.cpp index 59127246105d..e5d3c5ce5bc2 100644 --- a/lib/Analysis/BodyFarm.cpp +++ b/lib/Analysis/BodyFarm.cpp @@ -12,13 +12,20 @@ // //===----------------------------------------------------------------------===// -#include "BodyFarm.h" +#include "clang/Analysis/BodyFarm.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/NestedNameSpecifier.h" #include "clang/Analysis/CodeInjector.h" +#include "clang/Basic/OperatorKinds.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/Debug.h" + +#define DEBUG_TYPE "body-farm" using namespace clang; @@ -55,7 +62,8 @@ public: CompoundStmt *makeCompound(ArrayRef<Stmt*>); /// Create a new DeclRefExpr for the referenced variable. - DeclRefExpr *makeDeclRefExpr(const VarDecl *D); + DeclRefExpr *makeDeclRefExpr(const VarDecl *D, + bool RefersToEnclosingVariableOrCapture = false); /// Create a new UnaryOperator representing a dereference. UnaryOperator *makeDereference(const Expr *Arg, QualType Ty); @@ -66,9 +74,19 @@ public: /// Create an implicit cast to a builtin boolean type. ImplicitCastExpr *makeIntegralCastToBoolean(const Expr *Arg); - // Create an implicit cast for lvalue-to-rvaluate conversions. + /// Create an implicit cast for lvalue-to-rvaluate conversions. ImplicitCastExpr *makeLvalueToRvalue(const Expr *Arg, QualType Ty); + /// Make RValue out of variable declaration, creating a temporary + /// DeclRefExpr in the process. + ImplicitCastExpr * + makeLvalueToRvalue(const VarDecl *Decl, + bool RefersToEnclosingVariableOrCapture = false); + + /// Create an implicit cast of the given type. + ImplicitCastExpr *makeImplicitCast(const Expr *Arg, QualType Ty, + CastKind CK = CK_LValueToRValue); + /// Create an Objective-C bool literal. ObjCBoolLiteralExpr *makeObjCBool(bool Val); @@ -78,6 +96,18 @@ public: /// Create a Return statement. ReturnStmt *makeReturn(const Expr *RetVal); + /// Create an integer literal expression of the given type. + IntegerLiteral *makeIntegerLiteral(uint64_t Value, QualType Ty); + + /// Create a member expression. + MemberExpr *makeMemberExpression(Expr *base, ValueDecl *MemberDecl, + bool IsArrow = false, + ExprValueKind ValueKind = VK_LValue); + + /// Returns a *first* member field of a record declaration with a given name. + /// \return an nullptr if no member with such a name exists. + ValueDecl *findMemberField(const RecordDecl *RD, StringRef Name); + private: ASTContext &C; }; @@ -106,16 +136,14 @@ CompoundStmt *ASTMaker::makeCompound(ArrayRef<Stmt *> Stmts) { return new (C) CompoundStmt(C, Stmts, SourceLocation(), SourceLocation()); } -DeclRefExpr *ASTMaker::makeDeclRefExpr(const VarDecl *D) { - DeclRefExpr *DR = - DeclRefExpr::Create(/* Ctx = */ C, - /* QualifierLoc = */ NestedNameSpecifierLoc(), - /* TemplateKWLoc = */ SourceLocation(), - /* D = */ const_cast<VarDecl*>(D), - /* RefersToEnclosingVariableOrCapture = */ false, - /* NameLoc = */ SourceLocation(), - /* T = */ D->getType(), - /* VK = */ VK_LValue); +DeclRefExpr *ASTMaker::makeDeclRefExpr( + const VarDecl *D, + bool RefersToEnclosingVariableOrCapture) { + QualType Type = D->getType().getNonReferenceType(); + + DeclRefExpr *DR = DeclRefExpr::Create( + C, NestedNameSpecifierLoc(), SourceLocation(), const_cast<VarDecl *>(D), + RefersToEnclosingVariableOrCapture, SourceLocation(), Type, VK_LValue); return DR; } @@ -125,8 +153,25 @@ UnaryOperator *ASTMaker::makeDereference(const Expr *Arg, QualType Ty) { } ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) { - return ImplicitCastExpr::Create(C, Ty, CK_LValueToRValue, - const_cast<Expr*>(Arg), nullptr, VK_RValue); + return makeImplicitCast(Arg, Ty, CK_LValueToRValue); +} + +ImplicitCastExpr * +ASTMaker::makeLvalueToRvalue(const VarDecl *Arg, + bool RefersToEnclosingVariableOrCapture) { + QualType Type = Arg->getType().getNonReferenceType(); + return makeLvalueToRvalue(makeDeclRefExpr(Arg, + RefersToEnclosingVariableOrCapture), + Type); +} + +ImplicitCastExpr *ASTMaker::makeImplicitCast(const Expr *Arg, QualType Ty, + CastKind CK) { + return ImplicitCastExpr::Create(C, Ty, + /* CastKind=*/ CK, + /* Expr=*/ const_cast<Expr *>(Arg), + /* CXXCastPath=*/ nullptr, + /* ExprValueKind=*/ VK_RValue); } Expr *ASTMaker::makeIntegralCast(const Expr *Arg, QualType Ty) { @@ -161,12 +206,259 @@ ReturnStmt *ASTMaker::makeReturn(const Expr *RetVal) { nullptr); } +IntegerLiteral *ASTMaker::makeIntegerLiteral(uint64_t Value, QualType Ty) { + llvm::APInt APValue = llvm::APInt(C.getTypeSize(Ty), Value); + return IntegerLiteral::Create(C, APValue, Ty, SourceLocation()); +} + +MemberExpr *ASTMaker::makeMemberExpression(Expr *base, ValueDecl *MemberDecl, + bool IsArrow, + ExprValueKind ValueKind) { + + DeclAccessPair FoundDecl = DeclAccessPair::make(MemberDecl, AS_public); + return MemberExpr::Create( + C, base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(), + SourceLocation(), MemberDecl, FoundDecl, + DeclarationNameInfo(MemberDecl->getDeclName(), SourceLocation()), + /* TemplateArgumentListInfo=*/ nullptr, MemberDecl->getType(), ValueKind, + OK_Ordinary); +} + +ValueDecl *ASTMaker::findMemberField(const RecordDecl *RD, StringRef Name) { + + CXXBasePaths Paths( + /* FindAmbiguities=*/false, + /* RecordPaths=*/false, + /* DetectVirtual=*/ false); + const IdentifierInfo &II = C.Idents.get(Name); + DeclarationName DeclName = C.DeclarationNames.getIdentifier(&II); + + DeclContextLookupResult Decls = RD->lookup(DeclName); + for (NamedDecl *FoundDecl : Decls) + if (!FoundDecl->getDeclContext()->isFunctionOrMethod()) + return cast<ValueDecl>(FoundDecl); + + return nullptr; +} + //===----------------------------------------------------------------------===// // Creation functions for faux ASTs. //===----------------------------------------------------------------------===// typedef Stmt *(*FunctionFarmer)(ASTContext &C, const FunctionDecl *D); +static CallExpr *create_call_once_funcptr_call(ASTContext &C, ASTMaker M, + const ParmVarDecl *Callback, + ArrayRef<Expr *> CallArgs) { + + QualType Ty = Callback->getType(); + DeclRefExpr *Call = M.makeDeclRefExpr(Callback); + CastKind CK; + if (Ty->isRValueReferenceType()) { + CK = CK_LValueToRValue; + } else { + assert(Ty->isLValueReferenceType()); + CK = CK_FunctionToPointerDecay; + Ty = C.getPointerType(Ty.getNonReferenceType()); + } + + return new (C) + CallExpr(C, M.makeImplicitCast(Call, Ty.getNonReferenceType(), CK), + /*args=*/CallArgs, + /*QualType=*/C.VoidTy, + /*ExprValueType=*/VK_RValue, + /*SourceLocation=*/SourceLocation()); +} + +static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M, + const ParmVarDecl *Callback, + CXXRecordDecl *CallbackDecl, + ArrayRef<Expr *> CallArgs) { + assert(CallbackDecl != nullptr); + assert(CallbackDecl->isLambda()); + FunctionDecl *callOperatorDecl = CallbackDecl->getLambdaCallOperator(); + assert(callOperatorDecl != nullptr); + + DeclRefExpr *callOperatorDeclRef = + DeclRefExpr::Create(/* Ctx =*/ C, + /* QualifierLoc =*/ NestedNameSpecifierLoc(), + /* TemplateKWLoc =*/ SourceLocation(), + const_cast<FunctionDecl *>(callOperatorDecl), + /* RefersToEnclosingVariableOrCapture=*/ false, + /* NameLoc =*/ SourceLocation(), + /* T =*/ callOperatorDecl->getType(), + /* VK =*/ VK_LValue); + + return new (C) + CXXOperatorCallExpr(/*AstContext=*/C, OO_Call, callOperatorDeclRef, + /*args=*/CallArgs, + /*QualType=*/C.VoidTy, + /*ExprValueType=*/VK_RValue, + /*SourceLocation=*/SourceLocation(), FPOptions()); +} + +/// Create a fake body for std::call_once. +/// Emulates the following function body: +/// +/// \code +/// typedef struct once_flag_s { +/// unsigned long __state = 0; +/// } once_flag; +/// template<class Callable> +/// void call_once(once_flag& o, Callable func) { +/// if (!o.__state) { +/// func(); +/// } +/// o.__state = 1; +/// } +/// \endcode +static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) { + DEBUG(llvm::dbgs() << "Generating body for call_once\n"); + + // We need at least two parameters. + if (D->param_size() < 2) + return nullptr; + + ASTMaker M(C); + + const ParmVarDecl *Flag = D->getParamDecl(0); + const ParmVarDecl *Callback = D->getParamDecl(1); + + if (!Callback->getType()->isReferenceType()) { + llvm::dbgs() << "libcxx03 std::call_once implementation, skipping.\n"; + return nullptr; + } + if (!Flag->getType()->isReferenceType()) { + llvm::dbgs() << "unknown std::call_once implementation, skipping.\n"; + return nullptr; + } + + QualType CallbackType = Callback->getType().getNonReferenceType(); + + // Nullable pointer, non-null iff function is a CXXRecordDecl. + CXXRecordDecl *CallbackRecordDecl = CallbackType->getAsCXXRecordDecl(); + QualType FlagType = Flag->getType().getNonReferenceType(); + auto *FlagRecordDecl = dyn_cast_or_null<RecordDecl>(FlagType->getAsTagDecl()); + + if (!FlagRecordDecl) { + DEBUG(llvm::dbgs() << "Flag field is not a record: " + << "unknown std::call_once implementation, " + << "ignoring the call.\n"); + return nullptr; + } + + // We initially assume libc++ implementation of call_once, + // where the once_flag struct has a field `__state_`. + ValueDecl *FlagFieldDecl = M.findMemberField(FlagRecordDecl, "__state_"); + + // Otherwise, try libstdc++ implementation, with a field + // `_M_once` + if (!FlagFieldDecl) { + FlagFieldDecl = M.findMemberField(FlagRecordDecl, "_M_once"); + } + + if (!FlagFieldDecl) { + DEBUG(llvm::dbgs() << "No field _M_once or __state_ found on " + << "std::once_flag struct: unknown std::call_once " + << "implementation, ignoring the call."); + return nullptr; + } + + bool isLambdaCall = CallbackRecordDecl && CallbackRecordDecl->isLambda(); + if (CallbackRecordDecl && !isLambdaCall) { + DEBUG(llvm::dbgs() << "Not supported: synthesizing body for functors when " + << "body farming std::call_once, ignoring the call."); + return nullptr; + } + + SmallVector<Expr *, 5> CallArgs; + const FunctionProtoType *CallbackFunctionType; + if (isLambdaCall) { + + // Lambda requires callback itself inserted as a first parameter. + CallArgs.push_back( + M.makeDeclRefExpr(Callback, + /* RefersToEnclosingVariableOrCapture=*/ true)); + CallbackFunctionType = CallbackRecordDecl->getLambdaCallOperator() + ->getType() + ->getAs<FunctionProtoType>(); + } else if (!CallbackType->getPointeeType().isNull()) { + CallbackFunctionType = + CallbackType->getPointeeType()->getAs<FunctionProtoType>(); + } else { + CallbackFunctionType = CallbackType->getAs<FunctionProtoType>(); + } + + if (!CallbackFunctionType) + return nullptr; + + // First two arguments are used for the flag and for the callback. + if (D->getNumParams() != CallbackFunctionType->getNumParams() + 2) { + DEBUG(llvm::dbgs() << "Types of params of the callback do not match " + << "params passed to std::call_once, " + << "ignoring the call\n"); + return nullptr; + } + + // All arguments past first two ones are passed to the callback, + // and we turn lvalues into rvalues if the argument is not passed by + // reference. + for (unsigned int ParamIdx = 2; ParamIdx < D->getNumParams(); ParamIdx++) { + const ParmVarDecl *PDecl = D->getParamDecl(ParamIdx); + Expr *ParamExpr = M.makeDeclRefExpr(PDecl); + if (!CallbackFunctionType->getParamType(ParamIdx - 2)->isReferenceType()) { + QualType PTy = PDecl->getType().getNonReferenceType(); + ParamExpr = M.makeLvalueToRvalue(ParamExpr, PTy); + } + CallArgs.push_back(ParamExpr); + } + + CallExpr *CallbackCall; + if (isLambdaCall) { + + CallbackCall = create_call_once_lambda_call(C, M, Callback, + CallbackRecordDecl, CallArgs); + } else { + + // Function pointer case. + CallbackCall = create_call_once_funcptr_call(C, M, Callback, CallArgs); + } + + DeclRefExpr *FlagDecl = + M.makeDeclRefExpr(Flag, + /* RefersToEnclosingVariableOrCapture=*/true); + + + MemberExpr *Deref = M.makeMemberExpression(FlagDecl, FlagFieldDecl); + assert(Deref->isLValue()); + QualType DerefType = Deref->getType(); + + // Negation predicate. + UnaryOperator *FlagCheck = new (C) UnaryOperator( + /* input=*/ + M.makeImplicitCast(M.makeLvalueToRvalue(Deref, DerefType), DerefType, + CK_IntegralToBoolean), + /* opc=*/ UO_LNot, + /* QualType=*/ C.IntTy, + /* ExprValueKind=*/ VK_RValue, + /* ExprObjectKind=*/ OK_Ordinary, SourceLocation()); + + // Create assignment. + BinaryOperator *FlagAssignment = M.makeAssignment( + Deref, M.makeIntegralCast(M.makeIntegerLiteral(1, C.IntTy), DerefType), + DerefType); + + IfStmt *Out = new (C) + IfStmt(C, SourceLocation(), + /* IsConstexpr=*/ false, + /* init=*/ nullptr, + /* var=*/ nullptr, + /* cond=*/ FlagCheck, + /* then=*/ M.makeCompound({CallbackCall, FlagAssignment})); + + return Out; +} + /// Create a fake body for dispatch_once. static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) { // Check if we have at least two parameters. @@ -193,8 +485,8 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) { // sets it, and calls the block. Basically, an AST dump of: // // void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) { - // if (!*predicate) { - // *predicate = 1; + // if (*predicate != ~0l) { + // *predicate = ~0l; // block(); // } // } @@ -202,22 +494,26 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) { ASTMaker M(C); // (1) Create the call. - DeclRefExpr *DR = M.makeDeclRefExpr(Block); - ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty); - CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue, - SourceLocation()); + CallExpr *CE = new (C) CallExpr( + /*ASTContext=*/C, + /*StmtClass=*/M.makeLvalueToRvalue(/*Expr=*/Block), + /*args=*/None, + /*QualType=*/C.VoidTy, + /*ExprValueType=*/VK_RValue, + /*SourceLocation=*/SourceLocation()); // (2) Create the assignment to the predicate. - IntegerLiteral *IL = - IntegerLiteral::Create(C, llvm::APInt(C.getTypeSize(C.IntTy), (uint64_t) 1), - C.IntTy, SourceLocation()); + Expr *DoneValue = + new (C) UnaryOperator(M.makeIntegerLiteral(0, C.LongTy), UO_Not, C.LongTy, + VK_RValue, OK_Ordinary, SourceLocation()); + BinaryOperator *B = M.makeAssignment( M.makeDereference( M.makeLvalueToRvalue( M.makeDeclRefExpr(Predicate), PredicateQPtrTy), PredicateTy), - M.makeIntegralCast(IL, PredicateTy), + M.makeIntegralCast(DoneValue, PredicateTy), PredicateTy); // (3) Create the compound statement. @@ -233,14 +529,15 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) { PredicateQPtrTy), PredicateTy), PredicateTy); - - UnaryOperator *UO = new (C) UnaryOperator(LValToRva |