diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:08 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:08 +0000 |
commit | bab175ec4b075c8076ba14c762900392533f6ee4 (patch) | |
tree | 01f4f29419a2cb10abe13c1e63cd2a66068b0137 /lib/AST | |
parent | 8b7a8012d223fac5d17d16a66bb39168a9a1dfc0 (diff) |
Notes
Diffstat (limited to 'lib/AST')
47 files changed, 4184 insertions, 1348 deletions
diff --git a/lib/AST/APValue.cpp b/lib/AST/APValue.cpp index 3c587331ed077..488ad3373ca34 100644 --- a/lib/AST/APValue.cpp +++ b/lib/AST/APValue.cpp @@ -17,8 +17,6 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" #include "clang/AST/Type.h" -#include "clang/Basic/Diagnostic.h" -#include "llvm/ADT/SmallString.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -29,6 +27,7 @@ namespace { CharUnits Offset; unsigned PathLength; unsigned CallIndex; + bool IsNullPtr; }; } @@ -151,10 +150,11 @@ APValue::APValue(const APValue &RHS) : Kind(Uninitialized) { MakeLValue(); if (RHS.hasLValuePath()) setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(), - RHS.isLValueOnePastTheEnd(), RHS.getLValueCallIndex()); + RHS.isLValueOnePastTheEnd(), RHS.getLValueCallIndex(), + RHS.isNullPointer()); else setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(), - RHS.getLValueCallIndex()); + RHS.getLValueCallIndex(), RHS.isNullPointer()); break; case Array: MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize()); @@ -263,7 +263,7 @@ LLVM_DUMP_METHOD void APValue::dump() const { static double GetApproxValue(const llvm::APFloat &F) { llvm::APFloat V = F; bool ignored; - V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven, + V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven, &ignored); return V.convertToDouble(); } @@ -581,8 +581,13 @@ unsigned APValue::getLValueCallIndex() const { return ((const LV*)(const char*)Data.buffer)->CallIndex; } +bool APValue::isNullPointer() const { + assert(isLValue() && "Invalid usage"); + return ((const LV*)(const char*)Data.buffer)->IsNullPtr; +} + void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath, - unsigned CallIndex) { + unsigned CallIndex, bool IsNullPtr) { assert(isLValue() && "Invalid accessor"); LV &LVal = *((LV*)(char*)Data.buffer); LVal.BaseAndIsOnePastTheEnd.setPointer(B); @@ -590,11 +595,12 @@ void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath, LVal.Offset = O; LVal.CallIndex = CallIndex; LVal.resizePath((unsigned)-1); + LVal.IsNullPtr = IsNullPtr; } void APValue::setLValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd, - unsigned CallIndex) { + unsigned CallIndex, bool IsNullPtr) { assert(isLValue() && "Invalid accessor"); LV &LVal = *((LV*)(char*)Data.buffer); LVal.BaseAndIsOnePastTheEnd.setPointer(B); @@ -603,6 +609,7 @@ void APValue::setLValue(LValueBase B, const CharUnits &O, LVal.CallIndex = CallIndex; LVal.resizePath(Path.size()); memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry)); + LVal.IsNullPtr = IsNullPtr; } const ValueDecl *APValue::getMemberPointerDecl() const { diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 6aad4d1d570b2..1b5988d019880 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -34,7 +34,6 @@ #include "clang/Basic/Builtins.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/Capacity.h" @@ -652,6 +651,10 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( cast<TemplateTemplateParmDecl>(*P))); } + assert(!TTP->getRequiresClause() && + "Unexpected requires-clause on template template-parameter"); + Expr *const CanonRequiresClause = nullptr; + TemplateTemplateParmDecl *CanonTTP = TemplateTemplateParmDecl::Create(*this, getTranslationUnitDecl(), SourceLocation(), TTP->getDepth(), @@ -661,7 +664,8 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( TemplateParameterList::Create(*this, SourceLocation(), SourceLocation(), CanonParams, - SourceLocation())); + SourceLocation(), + CanonRequiresClause)); // Get the new insert position for the node we care about. Canonical = CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos); @@ -700,8 +704,8 @@ static const LangAS::Map *getAddressSpaceMap(const TargetInfo &T, // language-specific address space. static const unsigned FakeAddrSpaceMap[] = { 1, // opencl_global - 2, // opencl_local - 3, // opencl_constant + 3, // opencl_local + 2, // opencl_constant 4, // opencl_generic 5, // cuda_device 6, // cuda_constant @@ -788,7 +792,8 @@ ASTContext::~ASTContext() { MaterializedTemporaryValues) MTVPair.second->~APValue(); - llvm::DeleteContainerSeconds(MangleNumberingContexts); + for (const auto &Value : ModuleInitializers) + Value.second->~PerModuleInitializers(); } void ASTContext::ReleaseParentMapEntries() { @@ -902,6 +907,67 @@ void ASTContext::deduplicateMergedDefinitonsFor(NamedDecl *ND) { Merged.erase(std::remove(Merged.begin(), Merged.end(), nullptr), Merged.end()); } +void ASTContext::PerModuleInitializers::resolve(ASTContext &Ctx) { + if (LazyInitializers.empty()) + return; + + auto *Source = Ctx.getExternalSource(); + assert(Source && "lazy initializers but no external source"); + + auto LazyInits = std::move(LazyInitializers); + LazyInitializers.clear(); + + for (auto ID : LazyInits) + Initializers.push_back(Source->GetExternalDecl(ID)); + + assert(LazyInitializers.empty() && + "GetExternalDecl for lazy module initializer added more inits"); +} + +void ASTContext::addModuleInitializer(Module *M, Decl *D) { + // One special case: if we add a module initializer that imports another + // module, and that module's only initializer is an ImportDecl, simplify. + if (auto *ID = dyn_cast<ImportDecl>(D)) { + auto It = ModuleInitializers.find(ID->getImportedModule()); + + // Maybe the ImportDecl does nothing at all. (Common case.) + if (It == ModuleInitializers.end()) + return; + + // Maybe the ImportDecl only imports another ImportDecl. + auto &Imported = *It->second; + if (Imported.Initializers.size() + Imported.LazyInitializers.size() == 1) { + Imported.resolve(*this); + auto *OnlyDecl = Imported.Initializers.front(); + if (isa<ImportDecl>(OnlyDecl)) + D = OnlyDecl; + } + } + + auto *&Inits = ModuleInitializers[M]; + if (!Inits) + Inits = new (*this) PerModuleInitializers; + Inits->Initializers.push_back(D); +} + +void ASTContext::addLazyModuleInitializers(Module *M, ArrayRef<uint32_t> IDs) { + auto *&Inits = ModuleInitializers[M]; + if (!Inits) + Inits = new (*this) PerModuleInitializers; + Inits->LazyInitializers.insert(Inits->LazyInitializers.end(), + IDs.begin(), IDs.end()); +} + +ArrayRef<Decl*> ASTContext::getModuleInitializers(Module *M) { + auto It = ModuleInitializers.find(M); + if (It == ModuleInitializers.end()) + return None; + + auto *Inits = It->second; + Inits->resolve(*this); + return Inits->Initializers; +} + ExternCContextDecl *ASTContext::getExternCContextDecl() const { if (!ExternCContext) ExternCContext = ExternCContextDecl::Create(*this, getTranslationUnitDecl()); @@ -1204,9 +1270,8 @@ void ASTContext::setClassScopeSpecializationPattern(FunctionDecl *FD, } NamedDecl * -ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) { - llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos - = InstantiatedFromUsingDecl.find(UUD); +ASTContext::getInstantiatedFromUsingDecl(NamedDecl *UUD) { + auto Pos = InstantiatedFromUsingDecl.find(UUD); if (Pos == InstantiatedFromUsingDecl.end()) return nullptr; @@ -1214,11 +1279,15 @@ ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) { } void -ASTContext::setInstantiatedFromUsingDecl(UsingDecl *Inst, NamedDecl *Pattern) { +ASTContext::setInstantiatedFromUsingDecl(NamedDecl *Inst, NamedDecl *Pattern) { assert((isa<UsingDecl>(Pattern) || isa<UnresolvedUsingValueDecl>(Pattern) || isa<UnresolvedUsingTypenameDecl>(Pattern)) && "pattern decl is not a using decl"); + assert((isa<UsingDecl>(Inst) || + isa<UnresolvedUsingValueDecl>(Inst) || + isa<UnresolvedUsingTypenameDecl>(Inst)) && + "instantiation did not produce a using decl"); assert(!InstantiatedFromUsingDecl[Inst] && "pattern already exists"); InstantiatedFromUsingDecl[Inst] = Pattern; } @@ -1504,6 +1573,30 @@ bool ASTContext::isAlignmentRequired(QualType T) const { return isAlignmentRequired(T.getTypePtr()); } +unsigned ASTContext::getTypeAlignIfKnown(QualType T) const { + // An alignment on a typedef overrides anything else. + if (auto *TT = T->getAs<TypedefType>()) + if (unsigned Align = TT->getDecl()->getMaxAlignment()) + return Align; + + // If we have an (array of) complete type, we're done. + T = getBaseElementType(T); + if (!T->isIncompleteType()) + return getTypeAlign(T); + + // If we had an array type, its element type might be a typedef + // type with an alignment attribute. + if (auto *TT = T->getAs<TypedefType>()) + if (unsigned Align = TT->getDecl()->getMaxAlignment()) + return Align; + + // Otherwise, see if the declaration of the type had an attribute. + if (auto *TT = T->getAs<TagType>()) + return TT->getDecl()->getMaxAlignment(); + + return 0; +} + TypeInfo ASTContext::getTypeInfo(const Type *T) const { TypeInfoMap::iterator I = MemoizedTypeInfo.find(T); if (I != MemoizedTypeInfo.end()) @@ -1671,24 +1764,29 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Width = Target->getPointerWidth(0); Align = Target->getPointerAlign(0); break; - case BuiltinType::OCLSampler: - // Samplers are modeled as integers. - Width = Target->getIntWidth(); - Align = Target->getIntAlign(); + case BuiltinType::OCLSampler: { + auto AS = getTargetAddressSpace(LangAS::opencl_constant); + Width = Target->getPointerWidth(AS); + Align = Target->getPointerAlign(AS); break; + } case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: case BuiltinType::OCLQueue: case BuiltinType::OCLNDRange: case BuiltinType::OCLReserveID: -#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ - case BuiltinType::Id: -#include "clang/Basic/OpenCLImageTypes.def" - // Currently these types are pointers to opaque types. Width = Target->getPointerWidth(0); Align = Target->getPointerAlign(0); break; +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLImageTypes.def" + { + auto AS = getTargetAddressSpace(Target->getOpenCLImageAddrSpace()); + Width = Target->getPointerWidth(AS); + Align = Target->getPointerAlign(AS); + } } break; case Type::ObjCObjectPointer: @@ -1787,6 +1885,9 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { case Type::Paren: return getTypeInfo(cast<ParenType>(T)->getInnerType().getTypePtr()); + case Type::ObjCTypeParam: + return getTypeInfo(cast<ObjCTypeParamType>(T)->desugar().getTypePtr()); + case Type::Typedef: { const TypedefNameDecl *Typedef = cast<TypedefType>(T)->getDecl(); TypeInfo Info = getTypeInfo(Typedef->getUnderlyingType().getTypePtr()); @@ -2284,6 +2385,14 @@ static QualType getFunctionTypeWithExceptionSpec( Proto->getExtProtoInfo().withExceptionSpec(ESI)); } +bool ASTContext::hasSameFunctionTypeIgnoringExceptionSpec(QualType T, + QualType U) { + return hasSameType(T, U) || + (getLangOpts().CPlusPlus1z && + hasSameType(getFunctionTypeWithExceptionSpec(*this, T, EST_None), + getFunctionTypeWithExceptionSpec(*this, U, EST_None))); +} + void ASTContext::adjustExceptionSpec( FunctionDecl *FD, const FunctionProtoType::ExceptionSpecInfo &ESI, bool AsWritten) { @@ -3039,46 +3148,160 @@ ASTContext::getCanonicalFunctionResultType(QualType ResultType) const { return CanResultType; } -QualType -ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, - const FunctionProtoType::ExtProtoInfo &EPI) const { +static bool isCanonicalExceptionSpecification( + const FunctionProtoType::ExceptionSpecInfo &ESI, bool NoexceptInType) { + if (ESI.Type == EST_None) + return true; + if (!NoexceptInType) + return false; + + // C++17 onwards: exception specification is part of the type, as a simple + // boolean "can this function type throw". + if (ESI.Type == EST_BasicNoexcept) + return true; + + // A dynamic exception specification is canonical if it only contains pack + // expansions (so we can't tell whether it's non-throwing) and all its + // contained types are canonical. + if (ESI.Type == EST_Dynamic) { + bool AnyPackExpansions = false; + for (QualType ET : ESI.Exceptions) { + if (!ET.isCanonical()) + return false; + if (ET->getAs<PackExpansionType>()) + AnyPackExpansions = true; + } + return AnyPackExpansions; + } + + // A noexcept(expr) specification is (possibly) canonical if expr is + // value-dependent. + if (ESI.Type == EST_ComputedNoexcept) + return ESI.NoexceptExpr && ESI.NoexceptExpr->isValueDependent(); + + return false; +} + +QualType ASTContext::getFunctionTypeInternal( + QualType ResultTy, ArrayRef<QualType> ArgArray, + const FunctionProtoType::ExtProtoInfo &EPI, bool OnlyWantCanonical) const { size_t NumArgs = ArgArray.size(); // Unique functions, to guarantee there is only one function of a particular // structure. llvm::FoldingSetNodeID ID; FunctionProtoType::Profile(ID, ResultTy, ArgArray.begin(), NumArgs, EPI, - *this); + *this, true); + + QualType Canonical; + bool Unique = false; void *InsertPos = nullptr; - if (FunctionProtoType *FTP = - FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos)) - return QualType(FTP, 0); + if (FunctionProtoType *FPT = + FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos)) { + QualType Existing = QualType(FPT, 0); + + // If we find a pre-existing equivalent FunctionProtoType, we can just reuse + // it so long as our exception specification doesn't contain a dependent + // noexcept expression, or we're just looking for a canonical type. + // Otherwise, we're going to need to create a type + // sugar node to hold the concrete expression. + if (OnlyWantCanonical || EPI.ExceptionSpec.Type != EST_ComputedNoexcept || + EPI.ExceptionSpec.NoexceptExpr == FPT->getNoexceptExpr()) + return Existing; + + // We need a new type sugar node for this one, to hold the new noexcept + // expression. We do no canonicalization here, but that's OK since we don't + // expect to see the same noexcept expression much more than once. + Canonical = getCanonicalType(Existing); + Unique = true; + } + + bool NoexceptInType = getLangOpts().CPlusPlus1z; + bool IsCanonicalExceptionSpec = + isCanonicalExceptionSpecification(EPI.ExceptionSpec, NoexceptInType); // Determine whether the type being created is already canonical or not. - bool isCanonical = - EPI.ExceptionSpec.Type == EST_None && isCanonicalResultType(ResultTy) && - !EPI.HasTrailingReturn; + bool isCanonical = !Unique && IsCanonicalExceptionSpec && + isCanonicalResultType(ResultTy) && !EPI.HasTrailingReturn; for (unsigned i = 0; i != NumArgs && isCanonical; ++i) if (!ArgArray[i].isCanonicalAsParam()) isCanonical = false; - // If this type isn't canonical, get the canonical version of it. - // The exception spec is not part of the canonical type. - QualType Canonical; - if (!isCanonical) { + if (OnlyWantCanonical) + assert(isCanonical && + "given non-canonical parameters constructing canonical type"); + + // If this type isn't canonical, get the canonical version of it if we don't + // already have it. The exception spec is only partially part of the + // canonical type, and only in C++17 onwards. + if (!isCanonical && Canonical.isNull()) { SmallVector<QualType, 16> CanonicalArgs; CanonicalArgs.reserve(NumArgs); for (unsigned i = 0; i != NumArgs; ++i) CanonicalArgs.push_back(getCanonicalParamType(ArgArray[i])); + llvm::SmallVector<QualType, 8> ExceptionTypeStorage; FunctionProtoType::ExtProtoInfo CanonicalEPI = EPI; CanonicalEPI.HasTrailingReturn = false; - CanonicalEPI.ExceptionSpec = FunctionProtoType::ExceptionSpecInfo(); + + if (IsCanonicalExceptionSpec) { + // Exception spec is already OK. + } else if (NoexceptInType) { + switch (EPI.ExceptionSpec.Type) { + case EST_Unparsed: case EST_Unevaluated: case EST_Uninstantiated: + // We don't know yet. It shouldn't matter what we pick here; no-one + // should ever look at this. + LLVM_FALLTHROUGH; + case EST_None: case EST_MSAny: + CanonicalEPI.ExceptionSpec.Type = EST_None; + break; + + // A dynamic exception specification is almost always "not noexcept", + // with the exception that a pack expansion might expand to no types. + case EST_Dynamic: { + bool AnyPacks = false; + for (QualType ET : EPI.ExceptionSpec.Exceptions) { + if (ET->getAs<PackExpansionType>()) + AnyPacks = true; + ExceptionTypeStorage.push_back(getCanonicalType(ET)); + } + if (!AnyPacks) + CanonicalEPI.ExceptionSpec.Type = EST_None; + else { + CanonicalEPI.ExceptionSpec.Type = EST_Dynamic; + CanonicalEPI.ExceptionSpec.Exceptions = ExceptionTypeStorage; + } + break; + } + + case EST_DynamicNone: case EST_BasicNoexcept: + CanonicalEPI.ExceptionSpec.Type = EST_BasicNoexcept; + break; + + case EST_ComputedNoexcept: + llvm::APSInt Value(1); + auto *E = CanonicalEPI.ExceptionSpec.NoexceptExpr; + if (!E || !E->isIntegerConstantExpr(Value, *this, nullptr, + /*IsEvaluated*/false)) { + // This noexcept specification is invalid. + // FIXME: Should this be able to happen? + CanonicalEPI.ExceptionSpec.Type = EST_None; + break; + } + + CanonicalEPI.ExceptionSpec.Type = + Value.getBoolValue() ? EST_BasicNoexcept : EST_None; + break; + } + } else { + CanonicalEPI.ExceptionSpec = FunctionProtoType::ExceptionSpecInfo(); + } // Adjust the canonical function result type. CanQualType CanResultTy = getCanonicalFunctionResultType(ResultTy); - Canonical = getFunctionType(CanResultTy, CanonicalArgs, CanonicalEPI); + Canonical = + getFunctionTypeInternal(CanResultTy, CanonicalArgs, CanonicalEPI, true); // Get the new insert position for the node we care about. FunctionProtoType *NewIP = @@ -3121,14 +3344,14 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, FunctionProtoType::ExtProtoInfo newEPI = EPI; new (FTP) FunctionProtoType(ResultTy, ArgArray, Canonical, newEPI); Types.push_back(FTP); - FunctionProtoTypes.InsertNode(FTP, InsertPos); + if (!Unique) + FunctionProtoTypes.InsertNode(FTP, InsertPos); return QualType(FTP, 0); } -/// Return pipe type for the specified type. -QualType ASTContext::getPipeType(QualType T) const { +QualType ASTContext::getPipeType(QualType T, bool ReadOnly) const { llvm::FoldingSetNodeID ID; - PipeType::Profile(ID, T); + PipeType::Profile(ID, T, ReadOnly); void *InsertPos = 0; if (PipeType *PT = PipeTypes.FindNodeOrInsertPos(ID, InsertPos)) @@ -3138,19 +3361,27 @@ QualType ASTContext::getPipeType(QualType T) const { // either, so fill in the canonical type field. QualType Canonical; if (!T.isCanonical()) { - Canonical = getPipeType(getCanonicalType(T)); + Canonical = getPipeType(getCanonicalType(T), ReadOnly); // Get the new insert position for the node we care about. PipeType *NewIP = PipeTypes.FindNodeOrInsertPos(ID, InsertPos); assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } - PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical); + PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical, ReadOnly); Types.push_back(New); PipeTypes.InsertNode(New, InsertPos); return QualType(New, 0); } +QualType ASTContext::getReadPipeType(QualType T) const { + return getPipeType(T, true); +} + +QualType ASTContext::getWritePipeType(QualType T) const { + return getPipeType(T, false); +} + #ifndef NDEBUG static bool NeedsInjectedClassNameType(const RecordDecl *D) { if (!isa<CXXRecordDecl>(D)) return false; @@ -3641,6 +3872,44 @@ ASTContext::getDependentTemplateSpecializationType( return QualType(T, 0); } +void +ASTContext::getInjectedTemplateArgs(const TemplateParameterList *Params, + SmallVectorImpl<TemplateArgument> &Args) { + Args.reserve(Args.size() + Params->size()); + + for (NamedDecl *Param : *Params) { + TemplateArgument Arg; + if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { + QualType ArgType = getTypeDeclType(TTP); + if (TTP->isParameterPack()) + ArgType = getPackExpansionType(ArgType, None); + + Arg = TemplateArgument(ArgType); + } else if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) { + Expr *E = new (*this) DeclRefExpr( + NTTP, /*enclosing*/false, + NTTP->getType().getNonLValueExprType(*this), + Expr::getValueKindForType(NTTP->getType()), NTTP->getLocation()); + + if (NTTP->isParameterPack()) + E = new (*this) PackExpansionExpr(DependentTy, E, NTTP->getLocation(), + None); + Arg = TemplateArgument(E); + } else { + auto *TTP = cast<TemplateTemplateParmDecl>(Param); + if (TTP->isParameterPack()) + Arg = TemplateArgument(TemplateName(TTP), Optional<unsigned>()); + else + Arg = TemplateArgument(TemplateName(TTP)); + } + + if (Param->isTemplateParameterPack()) + Arg = TemplateArgument::CreatePackCopy(*this, Arg); + + Args.push_back(Arg); + } +} + QualType ASTContext::getPackExpansionType(QualType Pattern, Optional<unsigned> NumExpansions) { llvm::FoldingSetNodeID ID; @@ -3798,6 +4067,116 @@ QualType ASTContext::getObjCObjectType( return QualType(T, 0); } +/// Apply Objective-C protocol qualifiers to the given type. +/// If this is for the canonical type of a type parameter, we can apply +/// protocol qualifiers on the ObjCObjectPointerType. +QualType +ASTContext::applyObjCProtocolQualifiers(QualType type, + ArrayRef<ObjCProtocolDecl *> protocols, bool &hasError, + bool allowOnPointerType) const { + hasError = false; + + if (const ObjCTypeParamType *objT = + dyn_cast<ObjCTypeParamType>(type.getTypePtr())) { + return getObjCTypeParamType(objT->getDecl(), protocols); + } + + // Apply protocol qualifiers to ObjCObjectPointerType. + if (allowOnPointerType) { + if (const ObjCObjectPointerType *objPtr = + dyn_cast<ObjCObjectPointerType>(type.getTypePtr())) { + const ObjCObjectType *objT = objPtr->getObjectType(); + // Merge protocol lists and construct ObjCObjectType. + SmallVector<ObjCProtocolDecl*, 8> protocolsVec; + protocolsVec.append(objT->qual_begin(), + objT->qual_end()); + protocolsVec.append(protocols.begin(), protocols.end()); + ArrayRef<ObjCProtocolDecl *> protocols = protocolsVec; + type = getObjCObjectType( + objT->getBaseType(), + objT->getTypeArgsAsWritten(), + protocols, + objT->isKindOfTypeAsWritten()); + return getObjCObjectPointerType(type); + } + } + + // Apply protocol qualifiers to ObjCObjectType. + if (const ObjCObjectType *objT = dyn_cast<ObjCObjectType>(type.getTypePtr())){ + // FIXME: Check for protocols to which the class type is already + // known to conform. + + return getObjCObjectType(objT->getBaseType(), + objT->getTypeArgsAsWritten(), + protocols, + objT->isKindOfTypeAsWritten()); + } + + // If the canonical type is ObjCObjectType, ... + if (type->isObjCObjectType()) { + // Silently overwrite any existing protocol qualifiers. + // TODO: determine whether that's the right thing to do. + + // FIXME: Check for protocols to which the class type is already + // known to conform. + return getObjCObjectType(type, { }, protocols, false); + } + + // id<protocol-list> + if (type->isObjCIdType()) { + const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>(); + type = getObjCObjectType(ObjCBuiltinIdTy, { }, protocols, + objPtr->isKindOfType()); + return getObjCObjectPointerType(type); + } + + // Class<protocol-list> + if (type->isObjCClassType()) { + const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>(); + type = getObjCObjectType(ObjCBuiltinClassTy, { }, protocols, + objPtr->isKindOfType()); + return getObjCObjectPointerType(type); + } + + hasError = true; + return type; +} + +QualType +ASTContext::getObjCTypeParamType(const ObjCTypeParamDecl *Decl, + ArrayRef<ObjCProtocolDecl *> protocols, + QualType Canonical) const { + // Look in the folding set for an existing type. + llvm::FoldingSetNodeID ID; + ObjCTypeParamType::Profile(ID, Decl, protocols); + void *InsertPos = nullptr; + if (ObjCTypeParamType *TypeParam = + ObjCTypeParamTypes.FindNodeOrInsertPos(ID, InsertPos)) + return QualType(TypeParam, 0); + + if (Canonical.isNull()) { + // We canonicalize to the underlying type. + Canonical = getCanonicalType(Decl->getUnderlyingType()); + if (!protocols.empty()) { + // Apply the protocol qualifers. + bool hasError; + Canonical = applyObjCProtocolQualifiers(Canonical, protocols, hasError, + true/*allowOnPointerType*/); + assert(!hasError && "Error when apply protocol qualifier to bound type"); + } + } + + unsigned size = sizeof(ObjCTypeParamType); + size += protocols.size() * sizeof(ObjCProtocolDecl *); + void *mem = Allocate(size, TypeAlignment); + ObjCTypeParamType *newType = new (mem) + ObjCTypeParamType(Decl, Canonical, protocols); + + Types.push_back(newType); + ObjCTypeParamTypes.InsertNode(newType, InsertPos); + return QualType(newType, 0); +} + /// ObjCObjectAdoptsQTypeProtocols - Checks that protocols in IC's /// protocol list adopt all protocols in QT's qualified-id protocol /// list. @@ -3983,7 +4362,7 @@ QualType ASTContext::getDecltypeType(Expr *e, QualType UnderlyingType) const { DependentDecltypeType *Canon = DependentDecltypeTypes.FindNodeOrInsertPos(ID, InsertPos); if (!Canon) { - // Build a new, canonical typeof(expr) type. + // Build a new, canonical decltype(expr) type. Canon = new (*this, TypeAlignment) DependentDecltypeType(*this, e); DependentDecltypeTypes.InsertNode(Canon, InsertPos); } @@ -4590,7 +4969,15 @@ QualType ASTContext::getArrayDecayedType(QualType Ty) const { QualType PtrTy = getPointerType(PrettyArrayType->getElementType()); // int x[restrict 4] -> int *restrict - return getQualifiedType(PtrTy, PrettyArrayType->getIndexTypeQualifiers()); + QualType Result = getQualifiedType(PtrTy, + PrettyArrayType->getIndexTypeQualifiers()); + + // int x[_Nullable] -> int * _Nullable + if (auto Nullability = Ty->getNullability(*this)) { + Result = const_cast<ASTContext *>(this)->getAttributedType( + AttributedType::getNullabilityAttrKind(*Nullability), Result, Result); + } + return Result; } QualType ASTContext::getBaseElementType(const ArrayType *array) const { @@ -5223,8 +5610,9 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const { return S; } -bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, - std::string& S) { +std::string +ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl) const { + std::string S; // Encode result type. getObjCEncodingForType(Decl->getReturnType(), S); CharUnits ParmOffset; @@ -5235,8 +5623,8 @@ bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, if (sz.isZero()) continue; - assert (sz.isPositive() && - "getObjCEncodingForFunctionDecl - Incomplete param type"); + assert(sz.isPositive() && + "getObjCEncodingForFunctionDecl - Incomplete param type"); ParmOffset += sz; } S += charUnitsToString(ParmOffset); @@ -5258,7 +5646,7 @@ bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, ParmOffset += getObjCEncodingTypeSize(PType); } - return false; + return S; } /// getObjCEncodingForMethodParameter - Return the encoded type for a single @@ -5280,11 +5668,11 @@ void ASTContext::getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT, /// getObjCEncodingForMethodDecl - Return the encoded type for this method /// declaration. -bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, - std::string& S, - bool Extended) const { +std::string ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, + bool Extended) const { // FIXME: This is not very efficient. // Encode return type. + std::string S; getObjCEncodingForMethodParameter(Decl->getObjCDeclQualifier(), Decl->getReturnType(), S, Extended); // Compute size of all parameters. @@ -5330,7 +5718,7 @@ bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, ParmOffset += getObjCEncodingTypeSize(PType); } - return false; + return S; } ObjCPropertyImplDecl * @@ -5378,9 +5766,9 @@ ASTContext::getObjCPropertyImplDeclForPropertyDecl( /// kPropertyNonAtomic = 'N' // property non-atomic /// }; /// @endcode -void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, - const Decl *Container, - std::string& S) const { +std::string +ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, + const Decl *Container) const { // Collect information from the property implementation decl(s). bool Dynamic = false; ObjCPropertyImplDecl *SynthesizePID = nullptr; @@ -5394,7 +5782,7 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, } // FIXME: This is not very efficient. - S = "T"; + std::string S = "T"; // Encode result type. // GCC has some special rules regarding encoding of properties which @@ -5443,6 +5831,7 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, } // FIXME: OBJCGC: weak & strong + return S; } /// getLegacyIntegralTypeEncoding - @@ -5833,18 +6222,20 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, ObjCInterfaceDecl *OI = T->castAs<ObjCObjectType>()->getInterface(); S += '{'; S += OI->getObjCRuntimeNameAsString(); - S += '='; - SmallVector<const ObjCIvarDecl*, 32> Ivars; - DeepCollectObjCIvars(OI, true, Ivars); - for (unsigned i = 0, e = Ivars.size(); i != e; ++i) { - const FieldDecl *Field = cast<FieldDecl>(Ivars[i]); - if (Field->isBitField()) - getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field); - else - getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD, - false, false, false, false, false, - EncodePointerToObjCTypedef, - NotEncodedT); + if (ExpandStructures) { + S += '='; + SmallVector<const ObjCIvarDecl*, 32> Ivars; + DeepCollectObjCIvars(OI, true, Ivars); + for (unsigned i = 0, e = Ivars.size(); i != e; ++i) { + const FieldDecl *Field = cast<FieldDecl>(Ivars[i]); + if (Field->isBitField()) + getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field); + else + getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD, + false, false, false, false, false, + EncodePointerToObjCTypedef, + NotEncodedT); + } } S += '}'; return; @@ -6369,9 +6760,8 @@ CreateX86_64ABIBuiltinVaListDecl(const ASTContext *Context) { static TypedefDecl *CreatePNaClABIBuiltinVaListDecl(const ASTContext *Context) { // typedef int __builtin_va_list[4]; llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 4); - QualType IntArrayType - = Context->getConstantArrayType(Context->IntTy, - Size, ArrayType::Normal, 0); + QualType IntArrayType = + Context->getConstantArrayType(Context->IntTy, Size, ArrayType::Normal, 0); return Context->buildImplicitTypedef(IntArrayType, "__builtin_va_list"); } @@ -6567,7 +6957,7 @@ ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS, QualifiedTemplateName *QTN = QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos); if (!QTN) { - QTN = new (*this, llvm::alignOf<QualifiedTemplateName>()) + QTN = new (*this, alignof(QualifiedTemplateName)) QualifiedTemplateName(NNS, TemplateKeyword, Template); QualifiedTemplateNames.InsertNode(QTN, InsertPos); } @@ -6595,11 +6985,11 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); if (CanonNNS == NNS) { - QTN = new (*this, llvm::alignOf<DependentTemplateName>()) + QTN = new (*this, alignof(DependentTemplateName)) DependentTemplateName(NNS, Name); } else { TemplateName Canon = getDependentTemplateName(CanonNNS, Name); - QTN = new (*this, llvm::alignOf<DependentTemplateName>()) + QTN = new (*this, alignof(DependentTemplateName)) DependentTemplateName(NNS, Name, Canon); DependentTemplateName *CheckQTN = DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos); @@ -6631,13 +7021,13 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); if (CanonNNS == NNS) { - QTN = new (*this, llvm::alignOf<DependentTemplateName>()) + QTN = new (*this, alignof(DependentTemplateName)) DependentTemplateName(NNS, Operator); } else { TemplateName Canon = getDependentTemplateName(CanonNNS, Operator); - QTN = new (*this, llvm::alignOf<DependentTemplateName>()) + QTN = new (*this, alignof(DependentTemplateName)) DependentTemplateName(NNS, Operator, Canon); - + DependentTemplateName *CheckQTN = DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos); assert(!CheckQTN && "Dependent template name canonicalization broken"); @@ -7388,7 +7778,7 @@ bool ASTContext::typesAreCompatible(QualType LHS, QualType RHS, bool CompareUnqualified) { if (getLangOpts().CPlusPlus) return hasSameType(LHS, RHS); - + return !mergeTypes(LHS, RHS, false, CompareUnqualified).isNull(); } @@ -7902,21 +8292,9 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, } case Type::Pipe: { - // Merge two pointer types, while trying to preserve typedef info - QualType LHSValue = LHS->getAs<PipeType>()->getElementType(); - QualType RHSValue = RHS->getAs<PipeType>()->getElementType(); - if (Unqualified) { - LHSValue = LHSValue.getUnqualifiedType(); - RHSValue = RHSValue.getUnqualifiedType(); - } - QualType ResultType = mergeTypes(LHSValue, RHSValue, false, - Unqualified); - if (ResultType.isNull()) return QualType(); - if (getCanonicalType(LHSValue) == getCanonicalType(ResultType)) - return LHS; - if (getCanonicalType(RHSValue) == getCanonicalType(ResultType)) - return RHS; - return getPipeType(ResultType); + assert(LHS != RHS && + "Equivalent pipe types should have already been handled!"); + return QualType(); } } @@ -8197,6 +8575,10 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'z'!"); Type = Context.getSizeType(); break; + case 'w': // wchar_t. + assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'w'!"); + Type = Context.getWideCharType(); + break; case 'F': Type = Context.getCFConstantStringType(); break; @@ -8385,13 +8767,16 @@ QualType ASTContext::GetBuiltinType(unsigned Id, bool Variadic = (TypeStr[0] == '.'); - // We really shouldn't be making a no-proto type here, especially in C++. - if (ArgTypes.empty() && Variadic) + // We really shouldn't be making a no-proto type here. + if (ArgTypes.empty() && Variadic && !getLangOpts().CPlusPlus) return getFunctionNoProtoType(ResType, EI); FunctionProtoType::ExtProtoInfo EPI; EPI.ExtInfo = EI; EPI.Variadic = Variadic; + if (getLangOpts().CPlusPlus && BuiltinInfo.isNoThrow(Id)) + EPI.ExceptionSpec.Type = + getLangOpts().CPlusPlus11 ? EST_BasicNoexcept : EST_DynamicNone; return getFunctionType(ResType, ArgTypes, EPI); } @@ -8576,6 +8961,8 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { return !D->getDeclContext()->isDependentContext(); else if (isa<OMPDeclareReductionDecl>(D)) return !D->getDeclContext()->isDependentContext(); + else if (isa<ImportDecl>(D)) + return true; else return false; @@ -8613,15 +9000,10 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { } } - GVALinkage Linkage = GetGVALinkageForFunction(FD); - // static, static inline, always_inline, and extern inline functions can // always be deferred. Normal inline functions can be deferred in C99/C++. // Implicit template instantiations can also be deferred in C++. - if (Linkage == GVA_Internal || Linkage == GVA_AvailableExternally || - Linkage == GVA_DiscardableODR) - return false; - return true; + return !isDiscardableGVALinkage(GetGVALinkageForFunction(FD)); } const VarDecl *VD = cast<VarDecl>(D); @@ -8632,9 +9014,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { return false; // Variables that can be needed in other TUs are required. - GVALinkage L = GetGVALinkageForVariable(VD); - if (L != GVA_Internal && L != GVA_AvailableExternally && - L != GVA_DiscardableODR) + if (!isDiscardableGVALinkage(GetGVALinkageForVariable(VD))) return true; // Variables that have destruction with side-effects are required. @@ -8646,6 +9026,14 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { !VD->evaluateValue()) return true; + // Likewise, variables with tuple-like bindings are required if their + // bindings have side-effects. + if (auto *DD = dyn_cast<DecompositionDecl>(VD)) + for (auto *BD : DD->bindings()) + if (auto *BindingVD = BD->getHoldingVar()) + if (DeclMustBeEmitted(BindingVD)) + return true; + return false; } @@ -8785,13 +9173,14 @@ unsigned ASTContext::getStaticLocalNumber(const VarDecl *VD) const { MangleNumberingContext & ASTContext::getManglingNumberContext(const DeclContext *DC) { assert(LangOpts.CPlusPlus); // We don't need mangling numbers for plain C. - MangleNumberingContext *&MCtx = MangleNumberingContexts[DC]; + std::unique_ptr<MangleNumberingContext> &MCtx = MangleNumberingContexts[DC]; if (!MCtx) MCtx = createMangleNumberingContext(); return *MCtx; } -MangleNumberingContext *ASTContext::createMangleNumberingContext() const { +std::unique_ptr<MangleNumberingContext> +ASTContext::createMangleNumberingContext() const { return ABI->createMangleNumberingContext(); } @@ -8808,18 +9197,6 @@ void ASTContext::addCopyConstructorForExceptionObject(CXXRecordDecl *RD, cast<CXXConstructorDecl>(CD->getFirstDecl())); } -void ASTContext::addDefaultArgExprForConstructor(const CXXConstructorDecl *CD, - unsigned ParmIdx, Expr *DAE) { - ABI->addDefaultArgExprForConstructor( - cast<CXXConstructorDecl>(CD->getFirstDecl()), ParmIdx, DAE); -} - -Expr *ASTContext::getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, - unsigned ParmIdx) { - return ABI->getDefaultArgExprForConstructor( - cast<CXXConstructorDecl>(CD->getFirstDecl()), ParmIdx); -} - void ASTContext::addTypedefNameForUnnamedTagDecl(TagDecl *TD, TypedefNameDecl *DD) { return ABI->addTypedefNameForUnnamedTagDecl(TD, DD); @@ -9098,6 +9475,16 @@ ASTContext::ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, } +uint64_t ASTContext::getTargetNullPointerValue(QualType QT) const { + unsigned AS; + if (QT->getUnqualifiedDesugaredType()->isNullPtrType()) + AS = 0; + else + AS = QT->getPointeeType().getAddressSpace(); + + return getTargetInfo().getNullPointerValue(AS); +} + // Explicitly instantiate this in case a Redeclarable<T> is used from a TU that // doesn't include ASTContext.h template diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp index 0f5a8b5ae8926..03e6115a0dba1 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -20,7 +20,6 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" -#include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -937,6 +936,9 @@ class TemplateDiff { ++(*this); } + /// Return true if the iterator is non-singular. + bool isValid() const { return TST; } + /// isEnd - Returns true if the iterator is one past the end. bool isEnd() const { assert(TST && "InternalIterator is invalid with a null TST."); @@ -996,21 +998,21 @@ class TemplateDiff { } }; - bool UseDesugaredIterator; InternalIterator SugaredIterator; InternalIterator DesugaredIterator; public: TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST) - : UseDesugaredIterator(TST->isSugared() && !TST->isTypeAlias()), - SugaredIterator(TST), + : SugaredIterator(TST), DesugaredIterator( - GetTemplateSpecializationType(Context, TST->desugar())) {} + (TST->isSugared() && !TST->isTypeAlias()) + ? GetTemplateSpecializationType(Context, TST->desugar()) + : nullptr) {} /// &operator++ - Increment the iterator to the next template argument. TSTiterator &operator++() { ++SugaredIterator; - if (UseDesugaredIterator) + if (DesugaredIterator.isValid()) ++DesugaredIterator; return *this; } @@ -1033,12 +1035,12 @@ class TemplateDiff { /// hasDesugaredTA - Returns true if there is another TemplateArgument /// available. bool hasDesugaredTA() const { - return UseDesugaredIterator && !DesugaredIterator.isEnd(); + return DesugaredIterator.isValid() && !DesugaredIterator.isEnd(); } /// getDesugaredTA - Returns the desugared TemplateArgument. reference getDesugaredTA() const { - assert(UseDesugaredIterator && + assert(DesugaredIterator.isValid() && "Desugared TemplateArgument should not be used."); return *DesugaredIterator; } diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 872ba356a9b22..62261ccc905b6 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -428,6 +428,8 @@ namespace { void VisitFunctionDecl(const FunctionDecl *D); void VisitFieldDecl(const FieldDecl *D); void VisitVarDecl(const VarDecl *D); + void VisitDecompositionDecl(const DecompositionDecl *D); + void VisitBindingDecl(const BindingDecl *D); void VisitFileScopeAsmDecl(const FileScopeAsmDecl *D); void VisitImportDecl(const ImportDecl *D); void VisitPragmaCommentDecl(const PragmaCommentDecl *D); @@ -515,6 +517,8 @@ namespace { void VisitFloatingLiteral(const FloatingLiteral *Node); void VisitStringLiteral(const StringLiteral *Str); void VisitInitListExpr(const InitListExpr *ILE); + void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *ILE); + void VisitArrayInitIndexExpr(const ArrayInitIndexExpr *ILE); void VisitUnaryOperator(const UnaryOperator *Node); void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Node); void VisitMemberExpr(const MemberExpr *Node); @@ -543,6 +547,8 @@ namespace { dumpDecl(Node->getLambdaClass()); } void VisitSizeOfPackExpr(const SizeOfPackExpr *Node); + void + VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *Node); // ObjC void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node); @@ -1133,8 +1139,15 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { if (D->isPure()) OS << " pure"; - else if (D->isDeletedAsWritten()) + if (D->isDefaulted()) { + OS << " default"; + if (D->isDeleted()) + OS << "_delete"; + } + if (D->isDeletedAsWritten()) OS << " delete"; + if (D->isTrivial()) + OS << " trivial"; if (const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>()) { FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); @@ -1153,11 +1166,6 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { D->getTemplateSpecializationInfo()) dumpTemplateArgumentList(*FTSI->TemplateArguments); - for (ArrayRef<NamedDecl *>::iterator - I = D->getDeclsInPrototypeScope().begin(), - E = D->getDeclsInPrototypeScope().end(); I != E; ++I) - dumpDecl(*I); - if (!D->param_begin() && D->getNumParams()) dumpChild([=] { OS << "<<NULL params x " << D->getNumParams() << ">>"; }); else @@ -1217,6 +1225,19 @@ void ASTDumper::VisitVarDecl(const VarDecl *D) { } } +void ASTDumper::VisitDecompositionDecl(const DecompositionDecl *D) { + VisitVarDecl(D); + for (auto *B : D->bindings()) + dumpDecl(B); +} + +void ASTDumper::VisitBindingDecl(const BindingDecl *D) { + dumpName(D); + dumpType(D->getType()); + if (auto *E = D->getBinding()) + dumpStmt(E); +} + void ASTDumper::VisitFileScopeAsmDecl(const FileScopeAsmDecl *D) { dumpStmt(D->getAsmString()); } @@ -2005,6 +2026,14 @@ void ASTDumper::VisitInitListExpr(const InitListExpr *ILE) { } } +void ASTDumper::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) { + VisitExpr(E); +} + +void ASTDumper::VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E) { + VisitExpr(E); +} + void ASTDumper::VisitUnaryOperator(const UnaryOperator *Node) { VisitExpr(Node); OS << " " << (Node->isPostfix() ? "postfix" : "prefix") @@ -2179,6 +2208,11 @@ void ASTDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) { dumpTemplateArgument(A); } +void ASTDumper::VisitCXXDependentScopeMemberExpr( + const CXXDependentScopeMemberExpr *Node) { + VisitExpr(Node); + OS << " " << (Node->isArrow() ? "->" : ".") << Node->getMember(); +} //===----------------------------------------------------------------------===// // Obj-C Expressions @@ -2451,12 +2485,18 @@ void QualType::dump(const char *msg) const { dump(); } -LLVM_DUMP_METHOD void QualType::dump() const { - ASTDumper Dumper(llvm::errs(), nullptr, nullptr); +LLVM_DUMP_METHOD void QualType::dump() const { dump(llvm::errs()); } + +LLVM_DUMP_METHOD void QualType::dump(llvm::raw_ostream &OS) const { + ASTDumper Dumper(OS, nullptr, nullptr); Dumper.dumpTypeAsChild(*this); } -LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); } +LLVM_DUMP_METHOD void Type::dump() const { dump(llvm::errs()); } + +LLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS) const { + QualType(this, 0).dump(OS); +} //===----------------------------------------------------------------------===// // Decl method implementations diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index bc1f9f96a06b0..67e96ea828bdf 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -39,7 +39,9 @@ namespace clang { // Importing types QualType VisitType(const Type *T); + QualType VisitAtomicType(const AtomicType *T); QualType VisitBuiltinType(const BuiltinType *T); + QualType VisitDecayedType(const DecayedType *T); QualType VisitComplexType(const ComplexType *T); QualType VisitPointerType(const PointerType *T); QualType VisitBlockPointerType(const BlockPointerType *T); @@ -88,6 +90,8 @@ namespace clang { DeclarationNameInfo& To); void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false); + bool ImportCastPath(CastExpr *E, CXXCastPath &Path); + typedef DesignatedInitExpr::Designator Designator; Designator ImportDesignator(const Designator &D); @@ -123,6 +127,8 @@ namespace clang { TemplateParameterList *ImportTemplateParameterList( TemplateParameterList *Params); TemplateArgument ImportTemplateArgument(const TemplateArgument &From); + TemplateArgumentLoc ImportTemplateArgumentLoc( + const TemplateArgumentLoc &TALoc, bool &Error); bool ImportTemplateArguments(const TemplateArgument *FromArgs, unsigned NumFromArgs, SmallVectorImpl<TemplateArgument> &ToArgs); @@ -136,6 +142,7 @@ namespace clang { bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To); Decl *VisitDecl(Decl *D); Decl *VisitAccessSpecDecl(AccessSpecDecl *D); + Decl *VisitStaticAssertDecl(StaticAssertDecl *D); Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D); Decl *VisitNamespaceDecl(NamespaceDecl *D); Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias); @@ -152,6 +159,7 @@ namespace clang { Decl *VisitCXXConversionDecl(CXXConversionDecl *D); Decl *VisitFieldDecl(FieldDecl *D); Decl *VisitIndirectFieldDecl(IndirectFieldDecl *D); + Decl *VisitFriendDecl(FriendDecl *D); Decl *VisitObjCIvarDecl(ObjCIvarDecl *D); Decl *VisitVarDecl(VarDecl *D); Decl *VisitImplicitParamDecl(ImplicitParamDecl *D); @@ -242,16 +250,32 @@ namespace clang { Expr *VisitConditionalOperator(ConditionalOperator *E); Expr *VisitBinaryConditionalOperator(BinaryConditionalOperator *E); Expr *VisitOpaqueValueExpr(OpaqueValueExpr *E); + Expr *VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E); + Expr *VisitExpressionTraitExpr(ExpressionTraitExpr *E); + Expr *VisitArraySubscriptExpr(ArraySubscriptExpr *E); Expr *VisitCompoundAssignOperator(CompoundAssignOperator *E); Expr *VisitImplicitCastExpr(ImplicitCastExpr *E); - Expr *VisitCStyleCastExpr(CStyleCastExpr *E); + Expr *VisitExplicitCastExpr(ExplicitCastExpr *E); + Expr *VisitOffsetOfExpr(OffsetOfExpr *OE); + Expr *VisitCXXThrowExpr(CXXThrowExpr *E); + Expr *VisitCXXNoexceptExpr(CXXNoexceptExpr *E); + Expr *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E); + Expr *VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E); + Expr *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E); + Expr *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE); + Expr *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E); + Expr *VisitCXXNewExpr(CXXNewExpr *CE); + Expr *VisitCXXDeleteExpr(CXXDeleteExpr *E); Expr *VisitCXXConstructExpr(CXXConstructExpr *E); Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E); + Expr *VisitExprWithCleanups(ExprWithCleanups *EWC); Expr *VisitCXXThisExpr(CXXThisExpr *E); Expr *VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E); Expr *VisitMemberExpr(MemberExpr *E); Expr *VisitCallExpr(CallExpr *E); Expr *VisitInitListExpr(InitListExpr *E); + Expr *VisitArrayInitLoopExpr(ArrayInitLoopExpr *E); + Expr *VisitArrayInitIndexExpr(ArrayInitIndexExpr *E); Expr *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E); Expr *VisitCXXNamedCastExpr(CXXNamedCastExpr *E); @@ -272,13 +296,26 @@ namespace clang { bool Failed = false; std::transform(Ibegin, Iend, Obegin, [&ImporterRef, &Failed](ItemT *From) -> ItemT * { - ItemT *To = ImporterRef.Import(From); + ItemT *To = cast_or_null<ItemT>( + ImporterRef.Import(From)); if (!To && From) Failed = true; return To; }); return Failed; } + + template<typename InContainerTy, typename OutContainerTy> + bool ImportContainerChecked(const InContainerTy &InContainer, + OutContainerTy &OutContainer) { + return ImportArrayChecked(InContainer.begin(), InContainer.end(), + OutContainer.begin()); + } + + template<typename InContainerTy, typename OIter> + bool ImportArrayChecked(const InContainerTy &InContainer, OIter Obegin) { + return ImportArrayChecked(InContainer.begin(), InContainer.end(), Obegin); + } }; } @@ -897,6 +934,23 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, break; } + case Type::ObjCTypeParam: { + const ObjCTypeParamType *Obj1 = cast<ObjCTypeParamType>(T1); + const ObjCTypeParamType *Obj2 = cast<ObjCTypeParamType>(T2); + if (!IsStructurallyEquivalent(Context, Obj1->getDecl(), + Obj2->getDecl())) + return false; + + if (Obj1->getNumProtocols() != Obj2->getNumProtocols()) + return false; + for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) { + if (!IsStructurallyEquivalent(Context, + Obj1->getProtocol(I), + Obj2->getProtocol(I))) + return false; + } + break; + } case Type::ObjCObject: { const ObjCObjectType *Obj1 = cast<ObjCObjectType>(T1); const ObjCObjectType *Obj2 = cast<ObjCObjectType>(T2); @@ -1549,6 +1603,14 @@ QualType ASTNodeImporter::VisitType(const Type *T) { return QualType(); } +QualType ASTNodeImporter::VisitAtomicType(const AtomicType *T){ + QualType UnderlyingType = Importer.Import(T->getValueType()); + if(UnderlyingType.isNull()) + return QualType(); + + return Importer.getToContext().getAtomicType(UnderlyingType); +} + QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { switch (T->getKind()) { #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ @@ -1594,6 +1656,14 @@ QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { llvm_unreachable("Invalid BuiltinType Kind!"); } +QualType ASTNodeImporter::VisitDecayedType(const DecayedType *T) { + QualType OrigT = Importer.Import(T->getOriginalType()); + if (OrigT.isNull()) + return QualType(); + + return Importer.getToContext().getDecayedType(OrigT); +} + QualType ASTNodeImporter::VisitComplexType(const ComplexType *T) { QualType ToElementType = Importer.Import(T->getElementType()); if (ToElementType.isNull()) @@ -2250,23 +2320,25 @@ bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To, TemplateParameterList *ASTNodeImporter::ImportTemplateParameterList( TemplateParameterList *Params) { - SmallVector<NamedDecl *, 4> ToParams; - ToParams.reserve(Params->size()); - for (TemplateParameterList::iterator P = Params->begin(), - PEnd = Params->end(); - P != PEnd; ++P) { - Decl *To = Importer.Import(*P); - if (!To) + SmallVector<NamedDecl *, 4> ToParams(Params->size()); + if (ImportContainerChecked(*Params, ToParams)) + return nullptr; + + Expr *ToRequiresClause; + if (Expr *const R = Params->getRequiresClause()) { + ToRequiresClause = Importer.Import(R); + if (!ToRequiresClause) return nullptr; - - ToParams.push_back(cast<NamedDecl>(To)); + } else { + ToRequiresClause = nullptr; } - + return TemplateParameterList::Create(Importer.getToContext(), Importer.Import(Params->getTemplateLoc()), Importer.Import(Params->getLAngleLoc()), ToParams, - Importer.Import(Params->getRAngleLoc())); + Importer.Import(Params->getRAngleLoc()), + ToRequiresClause); } TemplateArgument @@ -2340,6 +2412,31 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) { llvm_unreachable("Invalid template argument kind"); } +TemplateArgumentLoc ASTNodeImporter::ImportTemplateArgumentLoc( + const TemplateArgumentLoc &TALoc, bool &Error) { + Error = false; + TemplateArgument Arg = ImportTemplateArgument(TALoc.getArgument()); + TemplateArgumentLocInfo FromInfo = TALoc.getLocInfo(); + TemplateArgumentLocInfo ToInfo; + if (Arg.getKind() == TemplateArgument::Expression) { + Expr *E = Importer.Import(FromInfo.getAsExpr()); + ToInfo = TemplateArgumentLocInfo(E); + if (!E) + Error = true; + } else if (Arg.getKind() == TemplateArgument::Type) { + if (TypeSourceInfo *TSI = Importer.Import(FromInfo.getAsTypeSourceInfo())) + ToInfo = TemplateArgumentLocInfo(TSI); + else + Error = true; + } else { + ToInfo = TemplateArgumentLocInfo( + Importer.Import(FromInfo.getTemplateQualifierLoc()), + Importer.Import(FromInfo.getTemplateNameLoc()), + Importer.Import(FromInfo.getTemplateEllipsisLoc())); + } + return TemplateArgumentLoc(Arg, ToInfo); +} + bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs, unsigned NumFromArgs, SmallVectorImpl<TemplateArgument> &ToArgs) { @@ -2454,6 +2551,35 @@ Decl *ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) { return accessSpecDecl; } +Decl *ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) { + DeclContext *DC = Importer.ImportContext(D->getDeclContext()); + if (!DC) + return nullptr; + + DeclContext *LexicalDC = DC; + + // Import the location of this declaration. + SourceLocation Loc = Importer.Import(D->getLocation()); + + Expr *AssertExpr = Importer.Import(D->getAssertExpr()); + if (!AssertExpr) + return nullptr; + + StringLiteral *FromMsg = D->getMessage(); + StringLiteral *ToMsg = cast_or_null<StringLiteral>(Importer.Import(FromMsg)); + if (!ToMsg && FromMsg) + return nullptr; + + StaticAssertDecl *ToD = StaticAssertDecl::Create( + Importer.getToContext(), DC, Loc, AssertExpr, ToMsg, + Importer.Import(D->getRParenLoc()), D->isFailed()); + + ToD->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToD); + Importer.Imported(D, ToD); + return ToD; +} + Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { // Import the major distinguishing characteristics of this namespace. DeclContext *DC, *LexicalDC; @@ -3303,6 +3429,70 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { return ToIndirectField; } +Decl *ASTNodeImporter::VisitFriendDecl(FriendDecl *D) { + // Import the major distinguishing characteristics of a declaration. + DeclContext *DC = Importer.ImportContext(D->getDeclContext()); + DeclContext *LexicalDC = D->getDeclContext() == D->getLexicalDeclContext() + ? DC : Importer.ImportContext(D->getLexicalDeclContext()); + if (!DC || !LexicalDC) + return nullptr; + + // Determine whether we've already imported this decl. + // FriendDecl is not a NamedDecl so we cannot use localUncachedLookup. + auto *RD = cast<CXXRecordDecl>(DC); + FriendDecl *ImportedFriend = RD->getFirstFriend(); + StructuralEquivalenceContext Context( + Importer.getFromContext(), Importer.getToContext(), + Importer.getNonEquivalentDecls(), false, false); + + while (ImportedFriend) { + if (D->getFriendDecl() && ImportedFriend->getFriendDecl()) { + if (Context.IsStructurallyEquivalent(D->getFriendDecl(), + ImportedFriend->getFriendDecl())) + return Importer.Imported(D, ImportedFriend); + + } else if (D->getFriendType() && ImportedFriend->getFriendType()) { + if (Importer.IsStructurallyEquivalent( + D->getFriendType()->getType(), + ImportedFriend->getFriendType()->getType(), true)) + return Importer.Imported(D, ImportedFriend); + } + ImportedFriend = ImportedFriend->getNextFriend(); + } + + // Not found. Create it. + FriendDecl::FriendUnion ToFU; + if (NamedDecl *FriendD = D->getFriendDecl()) + ToFU = cast_or_null<NamedDecl>(Importer.Import(FriendD)); + else + ToFU = Importer.Import(D->getFriendType()); + if (!ToFU) + return nullptr; + + SmallVector<TemplateParameterList *, 1> ToTPLists(D->NumTPLists); + TemplateParameterList **FromTPLists = + D->getTrailingObjects<TemplateParameterList *>(); + for (unsigned I = 0; I < D->NumTPLists; I++) { + TemplateParameterList *List = ImportTemplateParameterList(FromTPLists[I]); + if (!List) + return nullptr; + ToTPLists[I] = List; + } + + FriendDecl *FrD = FriendDecl::Create(Importer.getToContext(), DC, + Importer.Import(D->getLocation()), + ToFU, Importer.Import(D->getFriendLoc()), + ToTPLists); + + Importer.Imported(D, FrD); + RD->pushFriendDecl(FrD); + + FrD->setAccess(D->getAccess()); + FrD->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(FrD); + return FrD; +} + Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { // Import the major distinguishing characteristics of an ivar. DeclContext *DC, *LexicalDC; @@ -4859,11 +5049,10 @@ Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { } SmallVector<Expr *, 4> Exprs(S->getNumOutputs() + S->getNumInputs()); - if (ImportArrayChecked(S->begin_outputs(), S->end_outputs(), Exprs.begin())) + if (ImportContainerChecked(S->outputs(), Exprs)) return nullptr; - if (ImportArrayChecked(S->begin_inputs(), S->end_inputs(), - Exprs.begin() + S->getNumOutputs())) + if (ImportArrayChecked(S->inputs(), Exprs.begin() + S->getNumOutputs())) return nullptr; StringLiteral *AsmStr = cast_or_null<StringLiteral>( @@ -4906,8 +5095,8 @@ Stmt *ASTNodeImporter::VisitNullStmt(NullStmt *S) { Stmt *ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) { llvm::SmallVector<Stmt *, 8> ToStmts(S->size()); - - if (ImportArrayChecked(S->body_begin(), S->body_end(), ToStmts.begin())) + + if (ImportContainerChecked(S->body(), ToStmts)) return nullptr; SourceLocation ToLBraceLoc = Importer.Import(S->getLBracLoc()); @@ -5361,7 +5550,7 @@ Expr *ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) { return nullptr; return new (Importer.getToContext()) GNUNullExpr( - T, Importer.Import(E->getExprLoc())); + T, Importer.Import(E->getLocStart())); } Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) { @@ -5375,7 +5564,7 @@ Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) { return nullptr; return new (Importer.getToContext()) PredefinedExpr( - Importer.Import(E->getExprLoc()), T, E->getIdentType(), SL); + Importer.Import(E->getLocStart()), T, E->getIdentType(), SL); } Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { @@ -5394,6 +5583,20 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { if (T.isNull()) return nullptr; + + TemplateArgumentListInfo ToTAInfo; + TemplateArgumentListInfo *ResInfo = nullptr; + if (E->hasExplicitTemplateArgs()) { + for (const auto &FromLoc : E->template_arguments()) { + bool Error = false; + TemplateArgumentLoc ToTALoc = ImportTemplateArgumentLoc(FromLoc, Error); + if (Error) + return nullptr; + ToTAInfo.addArgument(ToTALoc); + } + ResInfo = &ToTAInfo; + } + DeclRefExpr *DRE = DeclRefExpr::Create(Importer.getToContext(), Importer.Import(E->getQualifierLoc()), Importer.Import(E->getTemplateKeywordLoc()), @@ -5401,8 +5604,7 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { E->refersToEnclosingVariableOrCapture(), Importer.Import(E->getLocation()), T, E->getValueKind(), - FoundD, - /*FIXME:TemplateArgs=*/nullptr); + FoundD, ResInfo); if (E->hadMultipleCandidates()) DRE->setHadMultipleCandidates(true); return DRE; @@ -5411,7 +5613,7 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { Expr *ASTNodeImporter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) - return NULL; + return nullptr; return new (Importer.getToContext()) ImplicitValueInitExpr(T); } @@ -5580,8 +5782,7 @@ Expr *ASTNodeImporter::VisitParenExpr(ParenExpr *E) { Expr *ASTNodeImporter::VisitParenListExpr(ParenListExpr *E) { SmallVector<Expr *, 4> Exprs(E->getNumExprs()); - if (ImportArrayChecked( - E->getExprs(), E->getExprs() + E->getNumExprs(), Exprs.begin())) + if (ImportContainerChecked(E->exprs(), Exprs)) return nullptr; return new (Importer.getToContext()) ParenListExpr( @@ -5719,6 +5920,38 @@ Expr *ASTNodeImporter::VisitBinaryConditionalOperator( T, E->getValueKind(), E->getObjectKind()); } +Expr *ASTNodeImporter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + TypeSourceInfo *ToQueried = Importer.Import(E->getQueriedTypeSourceInfo()); + if (!ToQueried) + return nullptr; + + Expr *Dim = Importer.Import(E->getDimensionExpression()); + if (!Dim && E->getDimensionExpression()) + return nullptr; + + return new (Importer.getToContext()) ArrayTypeTraitExpr( + Importer.Import(E->getLocStart()), E->getTrait(), ToQueried, + E->getValue(), Dim, Importer.Import(E->getLocEnd()), T); +} + +Expr *ASTNodeImporter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *ToQueried = Importer.Import(E->getQueriedExpression()); + if (!ToQueried) + return nullptr; + + return new (Importer.getToContext()) ExpressionTraitExpr( + Importer.Import(E->getLocStart()), E->getTrait(), ToQueried, + E->getValue(), Importer.Import(E->getLocEnd()), T); +} + Expr *ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) @@ -5729,10 +5962,28 @@ Expr *ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { return nullptr; return new (Importer.getToContext()) OpaqueValueExpr( - Importer.Import(E->getExprLoc()), T, E->getValueKind(), + Importer.Import(E->getLocation()), T, E->getValueKind(), E->getObjectKind(), SourceExpr); } +Expr *ASTNodeImporter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *ToLHS = Importer.Import(E->getLHS()); + if (!ToLHS) + return nullptr; + + Expr *ToRHS = Importer.Import(E->getRHS()); + if (!ToRHS) + return nullptr; + + return new (Importer.getToContext()) ArraySubscriptExpr( + ToLHS, ToRHS, T, E->getValueKind(), E->getObjectKind(), + Importer.Import(E->getRBracketLoc())); +} + Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) @@ -5763,11 +6014,14 @@ Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { E->isFPContractable()); } -static bool ImportCastPath(CastExpr *E, CXXCastPath &Path) { - if (E->path_empty()) return false; - - // TODO: import cast paths - return true; +bool ASTNodeImporter::ImportCastPath(CastExpr *CE, CXXCastPath &Path) { + for (auto I = CE->path_begin(), E = CE->path_end(); I != E; ++I) { + if (CXXBaseSpecifier *Spec = Importer.Import(*I)) + Path.push_back(Spec); + else + return true; + } + return false; } Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) { @@ -5787,7 +6041,7 @@ Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) { SubExpr, &BasePath, E->getValueKind()); } -Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) { +Expr *ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) return nullptr; @@ -5804,11 +6058,320 @@ Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) { if (ImportCastPath(E, BasePath)) return nullptr; - return CStyleCastExpr::Create(Importer.getToContext(), T, - E->getValueKind(), E->getCastKind(), - SubExpr, &BasePath, TInfo, - Importer.Import(E->getLParenLoc()), - Importer.Import(E->getRParenLoc())); + switch (E->getStmtClass()) { + case Stmt::CStyleCastExprClass: { + CStyleCastExpr *CCE = cast<CStyleCastExpr>(E); + return CStyleCastExpr::Create(Importer.getToContext(), T, + E->getValueKind(), E->getCastKind(), + SubExpr, &BasePath, TInfo, + Importer.Import(CCE->getLParenLoc()), + Importer.Import(CCE->getRParenLoc())); + } + + case Stmt::CXXFunctionalCastExprClass: { + CXXFunctionalCastExpr *FCE = cast<CXXFunctionalCastExpr>(E); + return CXXFunctionalCastExpr::Create(Importer.getToContext(), T, + E->getValueKind(), TInfo, + E->getCastKind(), SubExpr, &BasePath, + Importer.Import(FCE->getLParenLoc()), + Importer.Import(FCE->getRParenLoc())); + } + + case Stmt::ObjCBridgedCastExprClass: { + ObjCBridgedCastExpr *OCE = cast<ObjCBridgedCastExpr>(E); + return new (Importer.getToContext()) ObjCBridgedCastExpr( + Importer.Import(OCE->getLParenLoc()), OCE->getBridgeKind(), + E->getCastKind(), Importer.Import(OCE->getBridgeKeywordLoc()), + TInfo, SubExpr); + } + default: + break; // just fall through + } + + CXXNamedCastExpr *Named = cast<CXXNamedCastExpr>(E); + SourceLocation ExprLoc = Importer.Import(Named->getOperatorLoc()), + RParenLoc = Importer.Import(Named->getRParenLoc()); + SourceRange Brackets = Importer.Import(Named->getAngleBrackets()); + + switch (E->getStmtClass()) { + case Stmt::CXXStaticCastExprClass: + return CXXStaticCastExpr::Create(Importer.getToContext(), T, + E->getValueKind(), E->getCastKind(), + SubExpr, &BasePath, TInfo, + ExprLoc, RParenLoc, Brackets); + + case Stmt::CXXDynamicCastExprClass: + return CXXDynamicCastExpr::Create(Importer.getToContext(), T, + E->getValueKind(), E->getCastKind(), + SubExpr, &BasePath, TInfo, + ExprLoc, RParenLoc, Brackets); + + case Stmt::CXXReinterpretCastExprClass: + return CXXReinterpretCastExpr::Create(Importer.getToContext(), T, + E->getValueKind(), E->getCastKind(), + SubExpr, &BasePath, TInfo, + ExprLoc, RParenLoc, Brackets); + + case Stmt::CXXConstCastExprClass: + return CXXConstCastExpr::Create(Importer.getToContext(), T, + E->getValueKind(), SubExpr, TInfo, ExprLoc, + RParenLoc, Brackets); + default: + llvm_unreachable("Cast expression of unsupported type!"); + return nullptr; + } +} + +Expr *ASTNodeImporter::VisitOffsetOfExpr(OffsetOfExpr *OE) { + QualType T = Importer.Import(OE->getType()); + if (T.isNull()) + return nullptr; + + SmallVector<OffsetOfNode, 4> Nodes; + for (int I = 0, E = OE->getNumComponents(); I < E; ++I) { + const OffsetOfNode &Node = OE->getComponent(I); + + switch (Node.getKind()) { + case OffsetOfNode::Array: + Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()), + Node.getArrayExprIndex(), + Importer.Import(Node.getLocEnd()))); + break; + + case OffsetOfNode::Base: { + CXXBaseSpecifier *BS = Importer.Import(Node.getBase()); + if (!BS && Node.getBase()) + return nullptr; + Nodes.push_back(OffsetOfNode(BS)); + break; + } + case OffsetOfNode::Field: { + FieldDecl *FD = cast_or_null<FieldDecl>(Importer.Import(Node.getField())); + if (!FD) + return nullptr; + Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()), FD, + Importer.Import(Node.getLocEnd()))); + break; + } + case OffsetOfNode::Identifier: { + IdentifierInfo *ToII = Importer.Import(Node.getFieldName()); + if (!ToII) + return nullptr; + Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()), ToII, + Importer.Import(Node.getLocEnd()))); + break; + } + } + } + + SmallVector<Expr *, 4> Exprs(OE->getNumExpressions()); + for (int I = 0, E = OE->getNumExpressions(); I < E; ++I) { + Expr *ToIndexExpr = Importer.Import(OE->getIndexExpr(I)); + if (!ToIndexExpr) + return nullptr; + Exprs[I] = ToIndexExpr; + } + + TypeSourceInfo *TInfo = Importer.Import(OE->getTypeSourceInfo()); + if (!TInfo && OE->getTypeSourceInfo()) + return nullptr; + + return OffsetOfExpr::Create(Importer.getToContext(), T, + Importer.Import(OE->getOperatorLoc()), + TInfo, Nodes, Exprs, + Importer.Import(OE->getRParenLoc())); +} + +Expr *ASTNodeImporter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *Operand = Importer.Import(E->getOperand()); + if (!Operand) + return nullptr; + + CanThrowResult CanThrow; + if (E->isValueDependent()) + CanThrow = CT_Dependent; + else + CanThrow = E->getValue() ? CT_Can : CT_Cannot; + + return new (Importer.getToContext()) CXXNoexceptExpr( + T, Operand, CanThrow, + Importer.Import(E->getLocStart()), Importer.Import(E->getLocEnd())); +} + +Expr *ASTNodeImporter::VisitCXXThrowExpr(CXXThrowExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *SubExpr = Importer.Import(E->getSubExpr()); + if (!SubExpr && E->getSubExpr()) + return nullptr; + + return new (Importer.getToContext()) CXXThrowExpr( + SubExpr, T, Importer.Import(E->getThrowLoc()), + E->isThrownVariableInScope()); +} + +Expr *ASTNodeImporter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { + ParmVarDecl *Param = cast_or_null<ParmVarDecl>( + Importer.Import(E->getParam())); + if (!Param) + return nullptr; + + return CXXDefaultArgExpr::Create( + Importer.getToContext(), Importer.Import(E->getUsedLocation()), Param); +} + +Expr *ASTNodeImporter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + TypeSourceInfo *TypeInfo = Importer.Import(E->getTypeSourceInfo()); + if (!TypeInfo) + return nullptr; + + return new (Importer.getToContext()) CXXScalarValueInitExpr( + T, TypeInfo, Importer.Import(E->getRParenLoc())); +} + +Expr *ASTNodeImporter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { + Expr *SubExpr = Importer.Import(E->getSubExpr()); + if (!SubExpr) + return nullptr; + + auto *Dtor = cast_or_null<CXXDestructorDecl>( + Importer.Import(const_cast<CXXDestructorDecl *>( + E->getTemporary()->getDestructor()))); + if (!Dtor) + return nullptr; + + ASTContext &ToCtx = Importer.getToContext(); + CXXTemporary *Temp = CXXTemporary::Create(ToCtx, Dtor); + return CXXBindTemporaryExpr::Create(ToCtx, Temp, SubExpr); +} + +Expr *ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE) { + QualType T = Importer.Import(CE->getType()); + if (T.isNull()) + return nullptr; + + SmallVector<Expr *, 8> Args(CE->getNumArgs()); + if (ImportContainerChecked(CE->arguments(), Args)) + return nullptr; + + auto *Ctor = cast_or_null<CXXConstructorDecl>( + Importer.Import(CE->getConstructor())); + if (!Ctor) + return nullptr; + + return CXXTemporaryObjectExpr::Create( + Importer.getToContext(), T, + Importer.Import(CE->getLocStart()), + Ctor, + CE->isElidable(), + Args, + CE->hadMultipleCandidates(), + CE->isListInitialization(), + CE->isStdInitListInitialization(), + CE->requiresZeroInitialization(), + CE->getConstructionKind(), + Importer.Import(CE->getParenOrBraceRange())); +} + +Expr * +ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *TempE = Importer.Import(E->GetTemporaryExpr()); + if (!TempE) + return nullptr; + + ValueDecl *ExtendedBy = cast_or_null<ValueDecl>( + Importer.Import(const_cast<ValueDecl *>(E->getExtendingDecl()))); + if (!ExtendedBy && E->getExtendingDecl()) + return nullptr; + + auto *ToMTE = new (Importer.getToContext()) MaterializeTemporaryExpr( + T, TempE, E->isBoundToLvalueReference()); + + // FIXME: Should ManglingNumber get numbers associated with 'to' context? + ToMTE->setExtendingDecl(ExtendedBy, E->getManglingNumber()); + return ToMTE; +} + +Expr *ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *CE) { + QualType T = Importer.Import(CE->getType()); + if (T.isNull()) + return nullptr; + + SmallVector<Expr *, 4> PlacementArgs(CE->getNumPlacementArgs()); + if (ImportContainerChecked(CE->placement_arguments(), PlacementArgs)) + return nullptr; + + FunctionDecl *OperatorNewDecl = cast_or_null<FunctionDecl>( + Importer.Import(CE->getOperatorNew())); + if (!OperatorNewDecl && CE->getOperatorNew()) + return nullptr; + + FunctionDecl *OperatorDeleteDecl = cast_or_null<FunctionDecl>( + Importer.Import(CE->getOperatorDelete())); + if (!OperatorDeleteDecl && CE->getOperatorDelete()) + return nullptr; + + Expr *ToInit = Importer.Import(CE->getInitializer()); + if (!ToInit && CE->getInitializer()) + return nullptr; + + TypeSourceInfo *TInfo = Importer.Import(CE->getAllocatedTypeSourceInfo()); + if (!TInfo) + return nullptr; + + Expr *ToArrSize = Importer.Import(CE->getArraySize()); + if (!ToArrSize && CE->getArraySize()) + return nullptr; + + return new (Importer.getToContext()) CXXNewExpr( + Importer.getToContext(), + CE->isGlobalNew(), + OperatorNewDecl, OperatorDeleteDecl, + CE->passAlignment(), + CE->doesUsualArrayDeleteWantSize(), + PlacementArgs, + Importer.Import(CE->getTypeIdParens()), + ToArrSize, CE->getInitializationStyle(), ToInit, T, TInfo, + Importer.Import(CE->getSourceRange()), + Importer.Import(CE->getDirectInitRange())); +} + +Expr *ASTNodeImporter::VisitCXXDeleteExpr(CXXDeleteExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + FunctionDecl *OperatorDeleteDecl = cast_or_null<FunctionDecl>( + Importer.Import(E->getOperatorDelete())); + if (!OperatorDeleteDecl && E->getOperatorDelete()) + return nullptr; + + Expr *ToArg = Importer.Import(E->getArgument()); + if (!ToArg && E->getArgument()) + return nullptr; + + return new (Importer.getToContext()) CXXDeleteExpr( + T, E->isGlobalDelete(), + E->isArrayForm(), + E->isArrayFormAsWritten(), + E->doesUsualArrayDeleteWantSize(), + OperatorDeleteDecl, + ToArg, + Importer.Import(E->getLocStart())); } Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) { @@ -5822,8 +6385,7 @@ Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) { return nullptr; SmallVector<Expr *, 6> ToArgs(E->getNumArgs()); - if (ImportArrayChecked(E->getArgs(), E->getArgs() + E->getNumArgs(), - ToArgs.begin())) + if (ImportContainerChecked(E->arguments(), ToArgs)) return nullptr; return CXXConstructExpr::Create(Importer.getToContext(), T, @@ -5837,6 +6399,24 @@ Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) { Importer.Import(E->getParenOrBraceRange())); } +Expr *ASTNodeImporter::VisitExprWithCleanups(ExprWithCleanups *EWC) { + Expr *SubExpr = Importer.Import(EWC->getSubExpr()); + if (!SubExpr && EWC->getSubExpr()) + return nullptr; + + SmallVector<ExprWithCleanups::CleanupObject, 8> Objs(EWC->getNumObjects()); + for (unsigned I = 0, E = EWC->getNumObjects(); I < E; I++) + if (ExprWithCleanups::CleanupObject Obj = + cast_or_null<BlockDecl>(Importer.Import(EWC->getObject(I)))) + Objs[I] = Obj; + else + return nullptr; + + return ExprWithCleanups::Create(Importer.getToContext(), + SubExpr, EWC->cleanupsHaveSideEffects(), + Objs); +} + Expr *ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) @@ -5847,8 +6427,7 @@ Expr *ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { return nullptr; SmallVector<Expr *, 4> ToArgs(E->getNumArgs()); - - if (ImportArrayChecked(E->arg_begin(), E->arg_end(), ToArgs.begin())) + if (ImportContainerChecked(E->arguments(), ToArgs)) return nullptr; return new (Importer.getToContext()) CXXMemberCallExpr( @@ -5949,8 +6528,7 @@ Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) { return nullptr; llvm::SmallVector<Expr *, 4> Exprs(ILE->getNumInits()); - if (ImportArrayChecked( - ILE->getInits(), ILE->getInits() + ILE->getNumInits(), Exprs.begin())) + if (ImportContainerChecked(ILE->inits(), Exprs)) return nullptr; ASTContext &ToCtx = Importer.getToContext(); @@ -5988,6 +6566,30 @@ Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) { return To; } +Expr *ASTNodeImporter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) { + QualType ToType = Importer.Import(E->getType()); + if (ToType.isNull()) + return nullptr; + + Expr *ToCommon = Importer.Import(E->getCommonExpr()); + if (!ToCommon && E->getCommonExpr()) + return nullptr; + + Expr *ToSubExpr = Importer.Import(E->getSubExpr()); + if (!ToSubExpr && E->getSubExpr()) + return nullptr; + + return new (Importer.getToContext()) + ArrayInitLoopExpr(ToType, ToCommon, ToSubExpr); +} + +Expr *ASTNodeImporter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) { + QualType ToType = Importer.Import(E->getType()); + if (ToType.isNull()) + return nullptr; + return new (Importer.getToContext()) ArrayInitIndexExpr(ToType); +} + Expr *ASTNodeImporter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) { FieldDecl *ToField = llvm::dyn_cast_or_null<FieldDecl>( Importer.Import(DIE->getField())); @@ -6376,10 +6978,10 @@ SourceLocation ASTImporter::Import(SourceLocation FromLoc) { SourceManager &FromSM = FromContext.getSourceManager(); - // For now, map everything down to its spelling location, so that we + // For now, map everything down to its file location, so that we // don't have to import macro expansions. // FIXME: Import macro expansions! - FromLoc = FromSM.getSpellingLoc(FromLoc); + FromLoc = FromSM.getFileLoc(FromLoc); std::pair<FileID, unsigned> Decomposed = FromSM.getDecomposedLoc(FromLoc); SourceManager &ToSM = ToContext.getSourceManager(); FileID ToFileID = Import(Decomposed.first); @@ -6478,31 +7080,27 @@ CXXCtorInitializer *ASTImporter::Import(CXXCtorInitializer *From) { return new (ToContext) CXXCtorInitializer(ToContext, ToTInfo, Import(From->getLParenLoc()), ToExpr, Import(From->getRParenLoc())); - } else if (unsigned NumArrayIndices = From->getNumArrayIndices()) { - FieldDecl *ToField = - llvm::cast_or_null<FieldDecl>(Import(From->getMember())); - if (!ToField && From->getMember()) - return nullptr; - - SmallVector<VarDecl *, 4> ToAIs(NumArrayIndices); - - for (unsigned AII = 0; AII < NumArrayIndices; ++AII) { - VarDecl *ToArrayIndex = - dyn_cast_or_null<VarDecl>(Import(From->getArrayIndex(AII))); - if (!ToArrayIndex && From->getArrayIndex(AII)) - return nullptr; - } - - return CXXCtorInitializer::Create( - ToContext, ToField, Import(From->getMemberLocation()), - Import(From->getLParenLoc()), ToExpr, Import(From->getRParenLoc()), - ToAIs.data(), NumArrayIndices); } else { return nullptr; } } +CXXBaseSpecifier *ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) { + auto Pos = ImportedCXXBaseSpecifiers.find(BaseSpec); + if (Pos != ImportedCXXBaseSpecifiers.end()) + return Pos->second; + + CXXBaseSpecifier *Imported = new (ToContext) CXXBaseSpecifier( + Import(BaseSpec->getSourceRange()), + BaseSpec->isVirtual(), BaseSpec->isBaseOfClass(), + BaseSpec->getAccessSpecifierAsWritten(), + Import(BaseSpec->getTypeSourceInfo()), + Import(BaseSpec->getEllipsisLoc())); + ImportedCXXBaseSpecifiers[BaseSpec] = Imported; + return Imported; +} + void ASTImporter::ImportDefinition(Decl *From) { Decl *To = Import(From); if (!To) diff --git a/lib/AST/ASTTypeTraits.cpp b/lib/AST/ASTTypeTraits.cpp index 2336c98fe049e..461084ce707ce 100644 --- a/lib/AST/ASTTypeTraits.cpp +++ b/lib/AST/ASTTypeTraits.cpp @@ -23,6 +23,7 @@ namespace ast_type_traits { const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = { { NKI_None, "<None>" }, { NKI_None, "TemplateArgument" }, + { NKI_None, "TemplateName" }, { NKI_None, "NestedNameSpecifierLoc" }, { NKI_None, "QualType" }, { NKI_None, "TypeLoc" }, @@ -109,6 +110,8 @@ void DynTypedNode::print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const { if (const TemplateArgument *TA = get<TemplateArgument>()) TA->print(PP, OS); + else if (const TemplateName *TN = get<TemplateName>()) + TN->print(OS, PP); else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>()) NNS->print(OS, PP); else if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>()) @@ -132,6 +135,8 @@ void DynTypedNode::dump(llvm::raw_ostream &OS, SourceManager &SM) const { D->dump(OS); else if (const Stmt *S = get<Stmt>()) S->dump(OS, SM); + else if (const Type *T = get<Type>()) + T->dump(OS); else OS << "Unable to dump values of type " << NodeKind.asStringRef() << "\n"; } diff --git a/lib/AST/AttrImpl.cpp b/lib/AST/AttrImpl.cpp index cb608700133c0..b06b50c9b4b88 100644 --- a/lib/AST/AttrImpl.cpp +++ b/lib/AST/AttrImpl.cpp @@ -11,11 +11,10 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/Attr.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" #include "clang/AST/Expr.h" #include "clang/AST/Type.h" -#include "llvm/ADT/StringSwitch.h" using namespace clang; #include "clang/AST/AttrImpl.inc" diff --git a/lib/AST/CXXABI.h b/lib/AST/CXXABI.h index c23b9191c7ab6..924ef00e8147a 100644 --- a/lib/AST/CXXABI.h +++ b/lib/AST/CXXABI.h @@ -43,7 +43,8 @@ public: virtual bool isNearlyEmpty(const CXXRecordDecl *RD) const = 0; /// Returns a new mangling number context for this C++ ABI. - virtual MangleNumberingContext *createMangleNumberingContext() const = 0; + virtual std::unique_ptr<MangleNumberingContext> + createMangleNumberingContext() const = 0; /// Adds a mapping from class to copy constructor for this C++ ABI. virtual void addCopyConstructorForExceptionObject(CXXRecordDecl *, @@ -53,12 +54,6 @@ public: virtual const CXXConstructorDecl * getCopyConstructorForExceptionObject(CXXRecordDecl *) = 0; - virtual void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD, - unsigned ParmIdx, Expr *DAE) = 0; - - virtual Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, - unsigned ParmIdx) = 0; - virtual void addTypedefNameForUnnamedTagDecl(TagDecl *TD, TypedefNameDecl *DD) = 0; diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp index 6a6ca76a0165b..a97d6a22e7b3f 100644 --- a/lib/AST/CXXInheritance.cpp +++ b/lib/AST/CXXInheritance.cpp @@ -16,7 +16,6 @@ #include "clang/AST/RecordLayout.h" #include "llvm/ADT/SetVector.h" #include <algorithm> -#include <set> using namespace clang; diff --git a/lib/AST/Comment.cpp b/lib/AST/Comment.cpp index 893bdc5c17bf8..7a7d3dd8304e6 100644 --- a/lib/AST/Comment.cpp +++ b/lib/AST/Comment.cpp @@ -7,14 +7,13 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/ASTContext.h" #include "clang/AST/Comment.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/Basic/CharInfo.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" namespace clang { namespace comments { @@ -114,6 +113,65 @@ bool ParagraphComment::isWhitespaceNoCache() const { return true; } +static TypeLoc lookThroughTypedefOrTypeAliasLocs(TypeLoc &SrcTL) { + TypeLoc TL = SrcTL.IgnoreParens(); + + // Look through qualified types. + if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) + return QualifiedTL.getUnqualifiedLoc(); + // Look through pointer types. + if (PointerTypeLoc PointerTL = TL.getAs<PointerTypeLoc>()) + return PointerTL.getPointeeLoc().getUnqualifiedLoc(); + // Look through reference types. + if (ReferenceTypeLoc ReferenceTL = TL.getAs<ReferenceTypeLoc>()) + return ReferenceTL.getPointeeLoc().getUnqualifiedLoc(); + // Look through adjusted types. + if (AdjustedTypeLoc ATL = TL.getAs<AdjustedTypeLoc>()) + return ATL.getOriginalLoc(); + if (BlockPointerTypeLoc BlockPointerTL = TL.getAs<BlockPointerTypeLoc>()) + return BlockPointerTL.getPointeeLoc().getUnqualifiedLoc(); + if (MemberPointerTypeLoc MemberPointerTL = TL.getAs<MemberPointerTypeLoc>()) + return MemberPointerTL.getPointeeLoc().getUnqualifiedLoc(); + if (ElaboratedTypeLoc ETL = TL.getAs<ElaboratedTypeLoc>()) + return ETL.getNamedTypeLoc(); + + return TL; +} + +static bool getFunctionTypeLoc(TypeLoc TL, FunctionTypeLoc &ResFTL) { + TypeLoc PrevTL; + while (PrevTL != TL) { + PrevTL = TL; + TL = lookThroughTypedefOrTypeAliasLocs(TL); + } + + if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { + ResFTL = FTL; + return true; + } + + if (TemplateSpecializationTypeLoc STL = + TL.getAs<TemplateSpecializationTypeLoc>()) { + // If we have a typedef to a template specialization with exactly one + // template argument of a function type, this looks like std::function, + // boost::function, or other function wrapper. Treat these typedefs as + // functions. + if (STL.getNumArgs() != 1) + return false; + TemplateArgumentLoc MaybeFunction = STL.getArgLoc(0); + if (MaybeFunction.getArgument().getKind() != TemplateArgument::Type) + return false; + TypeSourceInfo *MaybeFunctionTSI = MaybeFunction.getTypeSourceInfo(); + TypeLoc TL = MaybeFunctionTSI->getTypeLoc().getUnqualifiedLoc(); + if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { + ResFTL = FTL; + return true; + } + } + + return false; +} + const char *ParamCommandComment::getDirectionAsString(PassDirection D) { switch (D) { case ParamCommandComment::In: @@ -227,90 +285,45 @@ void DeclInfo::fill() { case Decl::Namespace: Kind = NamespaceKind; break; + case Decl::TypeAlias: case Decl::Typedef: { Kind = TypedefKind; - // If this is a typedef to something we consider a function, extract + // If this is a typedef / using to something we consider a function, extract // arguments and return type. - const TypedefDecl *TD = cast<TypedefDecl>(CommentDecl); - const TypeSourceInfo *TSI = TD->getTypeSourceInfo(); + const TypeSourceInfo *TSI = + K == Decl::Typedef + ? cast<TypedefDecl>(CommentDecl)->getTypeSourceInfo() + : cast<TypeAliasDecl>(CommentDecl)->getTypeSourceInfo(); if (!TSI) break; TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc(); - while (true) { - TL = TL.IgnoreParens(); - // Look through qualified types. - if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) { - TL = QualifiedTL.getUnqualifiedLoc(); - continue; - } - // Look through pointer types. - if (PointerTypeLoc PointerTL = TL.getAs<PointerTypeLoc>()) { - TL = PointerTL.getPointeeLoc().getUnqualifiedLoc(); - continue; - } - // Look through reference types. - if (ReferenceTypeLoc ReferenceTL = TL.getAs<ReferenceTypeLoc>()) { - TL = ReferenceTL.getPointeeLoc().getUnqualifiedLoc(); - continue; - } - // Look through adjusted types. - if (AdjustedTypeLoc ATL = TL.getAs<AdjustedTypeLoc>()) { - TL = ATL.getOriginalLoc(); - continue; - } - if (BlockPointerTypeLoc BlockPointerTL = - TL.getAs<BlockPointerTypeLoc>()) { - TL = BlockPointerTL.getPointeeLoc().getUnqualifiedLoc(); - continue; - } - if (MemberPointerTypeLoc MemberPointerTL = - TL.getAs<MemberPointerTypeLoc>()) { - TL = MemberPointerTL.getPointeeLoc().getUnqualifiedLoc(); - continue; - } - if (ElaboratedTypeLoc ETL = TL.getAs<ElaboratedTypeLoc>()) { - TL = ETL.getNamedTypeLoc(); - continue; - } - // Is this a typedef for a function type? - if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { - Kind = FunctionKind; - ParamVars = FTL.getParams(); - ReturnType = FTL.getReturnLoc().getType(); - break; - } - if (TemplateSpecializationTypeLoc STL = - TL.getAs<TemplateSpecializationTypeLoc>()) { - // If we have a typedef to a template specialization with exactly one - // template argument of a function type, this looks like std::function, - // boost::function, or other function wrapper. Treat these typedefs as - // functions. - if (STL.getNumArgs() != 1) - break; - TemplateArgumentLoc MaybeFunction = STL.getArgLoc(0); - if (MaybeFunction.getArgument().getKind() != TemplateArgument::Type) - break; - TypeSourceInfo *MaybeFunctionTSI = MaybeFunction.getTypeSourceInfo(); - TypeLoc TL = MaybeFunctionTSI->getTypeLoc().getUnqualifiedLoc(); - if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { - Kind = FunctionKind; - ParamVars = FTL.getParams(); - ReturnType = FTL.getReturnLoc().getType(); - } - break; - } - break; + FunctionTypeLoc FTL; + if (getFunctionTypeLoc(TL, FTL)) { + Kind = FunctionKind; + ParamVars = FTL.getParams(); + ReturnType = FTL.getReturnLoc().getType(); } break; } - case Decl::TypeAlias: - Kind = TypedefKind; - break; case Decl::TypeAliasTemplate: { const TypeAliasTemplateDecl *TAT = cast<TypeAliasTemplateDecl>(CommentDecl); Kind = TypedefKind; TemplateKind = Template; TemplateParameters = TAT->getTemplateParameters(); + TypeAliasDecl *TAD = TAT->getTemplatedDecl(); + if (!TAD) + break; + + const TypeSourceInfo *TSI = TAD->getTypeSourceInfo(); + if (!TSI) + break; + TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc(); + FunctionTypeLoc FTL; + if (getFunctionTypeLoc(TL, FTL)) { + Kind = FunctionKind; + ParamVars = FTL.getParams(); + ReturnType = FTL.getReturnLoc().getType(); + } break; } case Decl::Enum: diff --git a/lib/AST/CommentBriefParser.cpp b/lib/AST/CommentBriefParser.cpp index 090b9211d4c19..eecea8fc11df8 100644 --- a/lib/AST/CommentBriefParser.cpp +++ b/lib/AST/CommentBriefParser.cpp @@ -9,7 +9,6 @@ #include "clang/AST/CommentBriefParser.h" #include "clang/AST/CommentCommandTraits.h" -#include "llvm/ADT/StringSwitch.h" namespace clang { namespace comments { diff --git a/lib/AST/CommentLexer.cpp b/lib/AST/CommentLexer.cpp index 57bfef08df6ea..65d0f56f09ab3 100644 --- a/lib/AST/CommentLexer.cpp +++ b/lib/AST/CommentLexer.cpp @@ -378,15 +378,17 @@ void Lexer::lexCommentText(Token &T) { if ((Info = Traits.getTypoCorrectCommandInfo(CommandName))) { StringRef CorrectedName = Info->Name; SourceLocation Loc = getSourceLocation(BufferPtr); - SourceRange CommandRange(Loc.getLocWithOffset(1), - getSourceLocation(TokenPtr)); + SourceLocation EndLoc = getSourceLocation(TokenPtr); + SourceRange FullRange = SourceRange(Loc, EndLoc); + SourceRange CommandRange(Loc.getLocWithOffset(1), EndLoc); Diag(Loc, diag::warn_correct_comment_command_name) - << CommandName << CorrectedName + << FullRange << CommandName << CorrectedName << FixItHint::CreateReplacement(CommandRange, CorrectedName); } else { formTokenWithChars(T, TokenPtr, tok::unknown_command); T.setUnknownCommandName(CommandName); - Diag(T.getLocation(), diag::warn_unknown_comment_command_name); + Diag(T.getLocation(), diag::warn_unknown_comment_command_name) + << SourceRange(T.getLocation(), T.getEndLocation()); return; } } diff --git a/lib/AST/CommentParser.cpp b/lib/AST/CommentParser.cpp index cb37ec35f4d39..c1c04239f58eb 100644 --- a/lib/AST/CommentParser.cpp +++ b/lib/AST/CommentParser.cpp @@ -40,11 +40,11 @@ class TextTokenRetokenizer { /// A position in \c Toks. struct Position { - unsigned CurToken; const char *BufferStart; const char *BufferEnd; const char *BufferPtr; SourceLocation BufferStartLoc; + unsigned CurToken; }; /// Current position in Toks. diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp index f5f4f70dcbbf4..d39a9b26b2a8d 100644 --- a/lib/AST/CommentSema.cpp +++ b/lib/AST/CommentSema.cpp @@ -950,20 +950,19 @@ unsigned Sema::resolveParmVarReference(StringRef Name, namespace { class SimpleTypoCorrector { + const NamedDecl *BestDecl; + StringRef Typo; const unsigned MaxEditDistance; - const NamedDecl *BestDecl; unsigned BestEditDistance; unsigned BestIndex; unsigned NextIndex; public: - SimpleTypoCorrector(StringRef Typo) : - Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3), - BestDecl(nullptr), BestEditDistance(MaxEditDistance + 1), - BestIndex(0), NextIndex(0) - { } + explicit SimpleTypoCorrector(StringRef Typo) + : BestDecl(nullptr), Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3), + BestEditDistance(MaxEditDistance + 1), BestIndex(0), NextIndex(0) {} void addDecl(const NamedDecl *ND); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index d1e8d25ea044b..c3fa1c87affd1 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1395,6 +1395,10 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, return clang::LinkageComputer::getLVForDecl(D, computation); } +void NamedDecl::printName(raw_ostream &os) const { + os << Name; +} + std::string NamedDecl::getQualifiedNameAsString() const { std::string QualName; llvm::raw_string_ostream OS(QualName); @@ -1481,7 +1485,7 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, OS << "::"; } - if (getDeclName()) + if (getDeclName() || isa<DecompositionDecl>(this)) OS << *this; else OS << "(anonymous)"; @@ -1922,6 +1926,9 @@ VarDecl::isThisDeclarationADefinition(ASTContext &C) const { // // FIXME: How do you declare (but not define) a partial specialization of // a static data member template outside the containing class? + if (isThisDeclarationADemotedDefinition()) + return DeclarationOnly; + if (isStaticDataMember()) { if (isOutOfLine() && !(getCanonicalDecl()->isInline() && @@ -2246,6 +2253,56 @@ bool VarDecl::checkInitIsICE() const { return Eval->IsICE; } +VarDecl *VarDecl::getTemplateInstantiationPattern() const { + // If it's a variable template specialization, find the template or partial + // specialization from which it was instantiated. + if (auto *VDTemplSpec = dyn_cast<VarTemplateSpecializationDecl>(this)) { + auto From = VDTemplSpec->getInstantiatedFrom(); + if (auto *VTD = From.dyn_cast<VarTemplateDecl *>()) { + while (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate()) { + if (NewVTD->isMemberSpecialization()) + break; + VTD = NewVTD; + } + return VTD->getTemplatedDecl()->getDefinition(); + } + if (auto *VTPSD = + From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) { + while (auto *NewVTPSD = VTPSD->getInstantiatedFromMember()) { + if (NewVTPSD->isMemberSpecialization()) + break; + VTPSD = NewVTPSD; + } + return VTPSD->getDefinition(); + } + } + + if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) { + if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) { + VarDecl *VD = getInstantiatedFromStaticDataMember(); + while (auto *NewVD = VD->getInstantiatedFromStaticDataMember()) + VD = NewVD; + return VD->getDefinition(); + } + } + + if (VarTemplateDecl *VarTemplate = getDescribedVarTemplate()) { + + while (VarTemplate->getInstantiatedFromMemberTemplate()) { + if (VarTemplate->isMemberSpecialization()) + break; + VarTemplate = VarTemplate->getInstantiatedFromMemberTemplate(); + } + + assert((!VarTemplate->getTemplatedDecl() || + !isTemplateInstantiation(getTemplateSpecializationKind())) && + "couldn't find pattern for variable instantiation"); + + return VarTemplate->getTemplatedDecl(); + } + return nullptr; +} + VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const { if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) return cast<VarDecl>(MSI->getInstantiatedFrom()); @@ -2592,7 +2649,7 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { return false; const auto *FPT = getType()->castAs<FunctionProtoType>(); - if (FPT->getNumParams() == 0 || FPT->getNumParams() > 2 || FPT->isVariadic()) + if (FPT->getNumParams() == 0 || FPT->getNumParams() > 3 || FPT->isVariadic()) return false; // If this is a single-parameter function, it must be a replaceable global @@ -2600,20 +2657,42 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { if (FPT->getNumParams() == 1) return true; - // Otherwise, we're looking for a second parameter whose type is - // 'const std::nothrow_t &', or, in C++1y, 'std::size_t'. - QualType Ty = FPT->getParamType(1); + unsigned Params = 1; + QualType Ty = FPT->getParamType(Params); ASTContext &Ctx = getASTContext(); + + auto Consume = [&] { + ++Params; + Ty = Params < FPT->getNumParams() ? FPT->getParamType(Params) : QualType(); + }; + + // In C++14, the next parameter can be a 'std::size_t' for sized delete. + bool IsSizedDelete = false; if (Ctx.getLangOpts().SizedDeallocation && - Ctx.hasSameType(Ty, Ctx.getSizeType())) - return true; - if (!Ty->isReferenceType()) - return false; - Ty = Ty->getPointeeType(); - if (Ty.getCVRQualifiers() != Qualifiers::Const) - return false; - const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); - return RD && isNamed(RD, "nothrow_t") && RD->isInStdNamespace(); + (getDeclName().getCXXOverloadedOperator() == OO_Delete || + getDeclName().getCXXOverloadedOperator() == OO_Array_Delete) && + Ctx.hasSameType(Ty, Ctx.getSizeType())) { + IsSizedDelete = true; + Consume(); + } + + // In C++17, the next parameter can be a 'std::align_val_t' for aligned + // new/delete. + if (Ctx.getLangOpts().AlignedAllocation && !Ty.isNull() && Ty->isAlignValT()) + Consume(); + + // Finally, if this is not a sized delete, the final parameter can + // be a 'const std::nothrow_t&'. + if (!IsSizedDelete && !Ty.isNull() && Ty->isReferenceType()) { + Ty = Ty->getPointeeType(); + if (Ty.getCVRQualifiers() != Qualifiers::Const) + return false; + const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); + if (RD && isNamed(RD, "nothrow_t") && RD->isInStdNamespace()) + Consume(); + } + + return Params == FPT->getNumParams(); } LanguageLinkage FunctionDecl::getLanguageLinkage() const { @@ -2653,9 +2732,14 @@ bool FunctionDecl::isGlobal() const { } bool FunctionDecl::isNoReturn() const { - return hasAttr<NoReturnAttr>() || hasAttr<CXX11NoReturnAttr>() || - hasAttr<C11NoReturnAttr>() || - getType()->getAs<FunctionType>()->getNoReturnAttr(); + if (hasAttr<NoReturnAttr>() || hasAttr<CXX11NoReturnAttr>() || + hasAttr<C11NoReturnAttr>()) + return true; + + if (auto *FnTy = getType()->getAs<FunctionType>()) + return FnTy->getNoReturnAttr(); + + return false; } void @@ -2756,28 +2840,6 @@ void FunctionDecl::setParams(ASTContext &C, } } -void FunctionDecl::setDeclsInPrototypeScope(ArrayRef<NamedDecl *> NewDecls) { - assert(DeclsInPrototypeScope.empty() && "Already has prototype decls!"); - - if (!NewDecls.empty()) { - NamedDecl **A = new (getASTContext()) NamedDecl*[NewDecls.size()]; - std::copy(NewDecls.begin(), NewDecls.end(), A); - DeclsInPrototypeScope = llvm::makeArrayRef(A, NewDecls.size()); - // Move declarations introduced in prototype to the function context. - for (auto I : NewDecls) { - DeclContext *DC = I->getDeclContext(); - // Forward-declared reference to an enumeration is not added to - // declaration scope, so skip declaration that is absent from its - // declaration contexts. - if (DC->containsDecl(I)) { - DC->removeDecl(I); - I->setDeclContext(this); - addDecl(I); - } - } - } -} - /// getMinRequiredArguments - Returns the minimum number of arguments /// needed to call this function. This may be fewer than the number of /// function parameters, if some of the parameters have default @@ -2964,7 +3026,8 @@ const Attr *FunctionDecl::getUnusedResultAttr() const { /// an externally visible symbol, but "extern inline" will not create an /// externally visible symbol. bool FunctionDecl::isInlineDefinitionExternallyVisible() const { - assert(doesThisDeclarationHaveABody() && "Must have the function definition"); + assert((doesThisDeclarationHaveABody() || willHaveBody()) && + "Must be a function definition"); assert(isInlined() && "Function must be inline"); ASTContext &Context = getASTContext(); @@ -3408,6 +3471,10 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { case Builtin::BIstrlen: return Builtin::BIstrlen; + case Builtin::BI__builtin_bzero: + case Builtin::BIbzero: + return Builtin::BIbzero; + default: if (isExternC()) { if (FnInfo->isStr("memset")) @@ -3430,6 +3497,8 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { return Builtin::BIstrndup; else if (FnInfo->isStr("strlen")) return Builtin::BIstrlen; + else if (FnInfo->isStr("bzero")) + return Builtin::BIbzero; } break; } @@ -4281,3 +4350,18 @@ SourceRange ImportDecl::getSourceRange() const { return SourceRange(getLocation(), getIdentifierLocs().back()); } + +//===----------------------------------------------------------------------===// +// ExportDecl Implementation +//===----------------------------------------------------------------------===// + +void ExportDecl::anchor() {} + +ExportDecl *ExportDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation ExportLoc) { + return new (C, DC) ExportDecl(DC, ExportLoc); +} + +ExportDecl *ExportDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) ExportDecl(nullptr, SourceLocation()); +} diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index bfb7d02b2955d..6111abab646e9 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -28,7 +28,6 @@ #include "clang/AST/StmtCXX.h" #include "clang/AST/Type.h" #include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> using namespace clang; @@ -46,8 +45,7 @@ void Decl::updateOutOfDate(IdentifierInfo &II) const { } #define DECL(DERIVED, BASE) \ - static_assert(llvm::AlignOf<Decl>::Alignment >= \ - llvm::AlignOf<DERIVED##Decl>::Alignment, \ + static_assert(alignof(Decl) >= alignof(DERIVED##Decl), \ "Alignment sufficient after objects prepended to " #DERIVED); #define ABSTRACT_DECL(DECL) #include "clang/AST/DeclNodes.inc" @@ -56,7 +54,7 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Context, unsigned ID, std::size_t Extra) { // Allocate an extra 8 bytes worth of storage, which ensures that the // resulting pointer will still be 8-byte aligned. - static_assert(sizeof(unsigned) * 2 >= llvm::AlignOf<Decl>::Alignment, + static_assert(sizeof(unsigned) * 2 >= alignof(Decl), "Decl won't be misaligned"); void *Start = Context.Allocate(Size + Extra + 8); void *Result = (char*)Start + 8; @@ -81,8 +79,7 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Ctx, // Ensure required alignment of the resulting object by adding extra // padding at the start if required. size_t ExtraAlign = - llvm::OffsetToAlignment(sizeof(Module *), - llvm::AlignOf<Decl>::Alignment); + llvm::OffsetToAlignment(sizeof(Module *), alignof(Decl)); char *Buffer = reinterpret_cast<char *>( ::operator new(ExtraAlign + sizeof(Module *) + Size + Extra, Ctx)); Buffer += ExtraAlign; @@ -112,12 +109,24 @@ const char *Decl::getDeclKindName() const { void Decl::setInvalidDecl(bool Invalid) { InvalidDecl = Invalid; assert(!isa<TagDecl>(this) || !cast<TagDecl>(this)->isCompleteDefinition()); - if (Invalid && !isa<ParmVarDecl>(this)) { + if (!Invalid) { + return; + } + + if (!isa<ParmVarDecl>(this)) { // Defensive maneuver for ill-formed code: we're likely not to make it to // a point where we set the access specifier, so default it to "public" // to avoid triggering asserts elsewhere in the front end. setAccess(AS_public); } + + // Marking a DecompositionDecl as invalid implies all the child BindingDecl's + // are invalid too. + if (DecompositionDecl *DD = dyn_cast<DecompositionDecl>(this)) { + for (BindingDecl *Binding : DD->bindings()) { + Binding->setInvalidDecl(); + } + } } const char *DeclContext::getDeclKindName() const { @@ -378,6 +387,22 @@ bool Decl::isReferenced() const { return false; } +bool Decl::isExported() const { + if (isModulePrivate()) + return false; + // Namespaces are always exported. + if (isa<TranslationUnitDecl>(this) || isa<NamespaceDecl>(this)) + return true; + // Otherwise, this is a strictly lexical check. + for (auto *DC = getLexicalDeclContext(); DC; DC = DC->getLexicalParent()) { + if (cast<Decl>(DC)->isModulePrivate()) + return false; + if (isa<ExportDecl>(DC)) + return true; + } + return false; +} + bool Decl::hasDefiningAttr() const { return hasAttr<AliasAttr>() || hasAttr<IFuncAttr>(); } @@ -401,11 +426,12 @@ const Attr *Decl::getDefiningAttr() const { /// diagnostics. static AvailabilityResult CheckAvailability(ASTContext &Context, const AvailabilityAttr *A, - std::string *Message) { - VersionTuple TargetMinVersion = - Context.getTargetInfo().getPlatformMinVersion(); + std::string *Message, + VersionTuple EnclosingVersion) { + if (EnclosingVersion.empty()) + EnclosingVersion = Context.getTargetInfo().getPlatformMinVersion(); - if (TargetMinVersion.empty()) + if (EnclosingVersion.empty()) return AR_Available; // Check if this is an App Extension "platform", and if so chop off @@ -450,7 +476,7 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, // Make sure that this declaration has already been introduced. if (!A->getIntroduced().empty() && - TargetMinVersion < A->getIntroduced()) { + EnclosingVersion < A->getIntroduced()) { if (Message) { Message->clear(); llvm::raw_string_ostream Out(*Message); @@ -464,7 +490,7 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, } // Make sure that this declaration hasn't been obsoleted. - if (!A->getObsoleted().empty() && TargetMinVersion >= A->getObsoleted()) { + if (!A->getObsoleted().empty() && EnclosingVersion >= A->getObsoleted()) { if (Message) { Message->clear(); llvm::raw_string_ostream Out(*Message); @@ -478,7 +504,7 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, } // Make sure that this declaration hasn't been deprecated. - if (!A->getDeprecated().empty() && TargetMinVersion >= A->getDeprecated()) { + if (!A->getDeprecated().empty() && EnclosingVersion >= A->getDeprecated()) { if (Message) { Message->clear(); llvm::raw_string_ostream Out(*Message); @@ -494,9 +520,10 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, return AR_Available; } -AvailabilityResult Decl::getAvailability(std::string *Message) const { +AvailabilityResult Decl::getAvailability(std::string *Message, + VersionTuple EnclosingVersion) const { if (auto *FTD = dyn_cast<FunctionTemplateDecl>(this)) - return FTD->getTemplatedDecl()->getAvailability(Message); + return FTD->getTemplatedDecl()->getAvailability(Message, EnclosingVersion); AvailabilityResult Result = AR_Available; std::string ResultMessage; @@ -521,7 +548,7 @@ AvailabilityResult Decl::getAvailability(std::string *Message) const { if (const auto *Availability = dyn_cast<AvailabilityAttr>(A)) { AvailabilityResult AR = CheckAvailability(getASTContext(), Availability, - Message); + Message, EnclosingVersion); if (AR == AR_Unavailable) return AR_Unavailable; @@ -580,8 +607,8 @@ bool Decl::isWeakImported() const { return true; if (const auto *Availability = dyn_cast<AvailabilityAttr>(A)) { - if (CheckAvailability(getASTContext(), Availability, - nullptr) == AR_NotYetIntroduced) + if (CheckAvailability(getASTContext(), Availability, nullptr, + VersionTuple()) == AR_NotYetIntroduced) return true; } } @@ -599,6 +626,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case CXXConversion: case EnumConstant: case Var: + case Binding: case ImplicitParam: case ParmVar: case ObjCMethod: @@ -623,11 +651,13 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case Typedef: case TypeAlias: case TypeAliasTemplate: - case UnresolvedUsingTypename: case TemplateTypeParm: case ObjCTypeParam: return IDNS_Ordinary | IDNS_Type; + case UnresolvedUsingTypename: + return IDNS_Ordinary | IDNS_Type | IDNS_Using; + case UsingShadow: return 0; // we'll actually overwrite this later @@ -635,6 +665,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { return IDNS_Ordinary | IDNS_Using; case Using: + case UsingPack: return IDNS_Using; case ObjCProtocol: @@ -670,6 +701,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case FriendTemplate: case AccessSpec: case LinkageSpec: + case Export: case FileScopeAsm: case StaticAssert: case ObjCPropertyImpl: @@ -679,6 +711,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case Captured: case TranslationUnit: case ExternCContext: + case Decomposition: case UsingDirective: case BuiltinTemplate: @@ -954,7 +987,7 @@ bool DeclContext::isDependentContext() const { bool DeclContext::isTransparentContext() const { if (DeclKind == Decl::Enum) return !cast<EnumDecl>(this)->isScoped(); - else if (DeclKind == Decl::LinkageSpec) + else if (DeclKind == Decl::LinkageSpec || DeclKind == Decl::Export) return true; return false; @@ -974,6 +1007,18 @@ bool DeclContext::isExternCContext() const { return isLinkageSpecContext(this, clang::LinkageSpecDecl::lang_c); } +const LinkageSpecDecl *DeclContext::getExternCContext() const { + const DeclContext *DC = this; + while (DC->getDeclKind() != Decl::TranslationUnit) { + if (DC->getDeclKind() == Decl::LinkageSpec && + cast<LinkageSpecDecl>(DC)->getLanguage() == + clang::LinkageSpecDecl::lang_c) + return cast<LinkageSpecDecl>(DC); + DC = DC->getLexicalParent(); + } + return nullptr; +} + bool DeclContext::isExternCXXContext() const { return isLinkageSpecContext(this, clang::LinkageSpecDecl::lang_cxx); } @@ -993,6 +1038,7 @@ DeclContext *DeclContext::getPrimaryContext() { case Decl::TranslationUnit: case Decl::ExternCContext: case Decl::LinkageSpec: + case Decl::Export: case Decl::Block: case Decl::Captured: case Decl::OMPDeclareReduction: @@ -1405,8 +1451,8 @@ NamedDecl *const DeclContextLookupResult::SingleElementDummyList = nullptr; DeclContext::lookup_result DeclContext::lookup(DeclarationName Name) const { - assert(DeclKind != Decl::LinkageSpec && - "Should not perform lookups into linkage specs!"); + assert(DeclKind != Decl::LinkageSpec && DeclKind != Decl::Export && + "should not perform lookups into transparent contexts"); const DeclContext *PrimaryContext = getPrimaryContext(); if (PrimaryContext != this) @@ -1467,8 +1513,8 @@ DeclContext::lookup(DeclarationName Name) const { DeclContext::lookup_result DeclContext::noload_lookup(DeclarationName Name) { - assert(DeclKind != Decl::LinkageSpec && - "Should not perform lookups into linkage specs!"); + assert(DeclKind != Decl::LinkageSpec && DeclKind != Decl::Export && + "should not perform lookups into transparent contexts"); DeclContext *PrimaryContext = getPrimaryContext(); if (PrimaryContext != this) diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 81f94148d6ed3..a9db65a515184 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -533,6 +533,12 @@ void CXXRecordDecl::addedMember(Decl *D) { } else if (Constructor->isMoveConstructor()) SMKind |= SMF_MoveConstructor; } + + // C++11 [dcl.init.aggr]p1: DR1518 + // An aggregate is an array or a class with no user-provided, explicit, or + // inherited constructors + if (Constructor->isUserProvided() || Constructor->isExplicit()) + data().Aggregate = false; } // Handle constructors, including those inherited from base classes. @@ -546,20 +552,6 @@ void CXXRecordDecl::addedMember(Decl *D) { // constructor [...] if (Constructor->isConstexpr() && !Constructor->isCopyOrMoveConstructor()) data().HasConstexprNonCopyMoveConstructor = true; - - // C++ [dcl.init.aggr]p1: - // An aggregate is an array or a class with no user-declared - // constructors [...]. - // C++11 [dcl.init.aggr]p1: - // An aggregate is an array or a class with no user-provided - // constructors [...]. - // C++11 [dcl.init.aggr]p1: - // An aggregate is an array or a class with no user-provided - // constructors (including those inherited from a base class) [...]. - if (getASTContext().getLangOpts().CPlusPlus11 - ? Constructor->isUserProvided() - : !Constructor->isImplicit()) - data().Aggregate = false; } // Handle destructors. @@ -739,7 +731,7 @@ void CXXRecordDecl::addedMember(Decl *D) { } if (!Field->hasInClassInitializer() && !Field->isMutable()) { - if (CXXRecordDecl *FieldType = Field->getType()->getAsCXXRecordDecl()) { + if (CXXRecordDecl *FieldType = T->getAsCXXRecordDecl()) { if (FieldType->hasDefinition() && !FieldType->allowConstDefaultInit()) data().HasUninitializedFields = true; } else { @@ -989,8 +981,12 @@ void CXXRecordDecl::addedMember(Decl *D) { if (UsingDecl *Using = dyn_cast<UsingDecl>(D)) { if (Using->getDeclName().getNameKind() == - DeclarationName::CXXConstructorName) + DeclarationName::CXXConstructorName) { data().HasInheritedConstructor = true; + // C++1z [dcl.init.aggr]p1: + // An aggregate is [...] a class [...] with no inherited constructors + data().Aggregate = false; + } if (Using->getDeclName().getCXXOverloadedOperator() == OO_Equal) data().HasInheritedAssignment = true; @@ -1107,6 +1103,12 @@ CXXRecordDecl::getGenericLambdaTemplateParameterList() const { return nullptr; } +Decl *CXXRecordDecl::getLambdaContextDecl() const { + assert(isLambda() && "Not a lambda closure type!"); + ExternalASTSource *Source = getParentASTContext().getExternalSource(); + return getLambdaData().ContextDecl.get(Source); +} + static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) { QualType T = cast<CXXConversionDecl>(Conv->getUnderlyingDecl()->getAsFunction()) @@ -1571,17 +1573,35 @@ bool CXXMethodDecl::isUsualDeallocationFunction() const { // deallocation function. [...] if (getNumParams() == 1) return true; - - // C++ [basic.stc.dynamic.deallocation]p2: + unsigned UsualParams = 1; + + // C++ <=14 [basic.stc.dynamic.deallocation]p2: // [...] If class T does not declare such an operator delete but does // declare a member deallocation function named operator delete with // exactly two parameters, the second of which has type std::size_t (18.1), // then this function is a usual deallocation function. + // + // C++17 says a usual deallocation function is one with the signature + // (void* [, size_t] [, std::align_val_t] [, ...]) + // and all such functions are usual deallocation functions. It's not clear + // that allowing varargs functions was intentional. ASTContext &Context = getASTContext(); - if (getNumParams() != 2 || - !Context.hasSameUnqualifiedType(getParamDecl(1)->getType(), - Context.getSizeType())) + if (UsualParams < getNumParams() && + Context.hasSameUnqualifiedType(getParamDecl(UsualParams)->getType(), + Context.getSizeType())) + ++UsualParams; + + if (UsualParams < getNumParams() && + getParamDecl(UsualParams)->getType()->isAlignValT()) + ++UsualParams; + + if (UsualParams != getNumParams()) return false; + + // In C++17 onwards, all potential usual deallocation functions are actual + // usual deallocation functions. + if (Context.getLangOpts().AlignedAllocation) + return true; // This function is a usual deallocation function if there are no // single-parameter deallocation functions of the same kind. @@ -1714,7 +1734,7 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, SourceLocation EllipsisLoc) : Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init), LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual), - IsWritten(false), SourceOrderOrNumArrayIndices(0) + IsWritten(false), SourceOrder(0) { } @@ -1725,7 +1745,7 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, SourceLocation R) : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), - IsWritten(false), SourceOrderOrNumArrayIndices(0) + IsWritten(false), SourceOrder(0) { } @@ -1736,7 +1756,7 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, SourceLocation R) : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), - IsWritten(false), SourceOrderOrNumArrayIndices(0) + IsWritten(false), SourceOrder(0) { } @@ -1746,38 +1766,10 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, SourceLocation R) : Initializee(TInfo), MemberOrEllipsisLocation(), Init(Init), LParenLoc(L), RParenLoc(R), IsDelegating(true), IsVirtual(false), - IsWritten(false), SourceOrderOrNumArrayIndices(0) + IsWritten(false), SourceOrder(0) { } -CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, - FieldDecl *Member, - SourceLocation MemberLoc, - SourceLocation L, Expr *Init, - SourceLocation R, - VarDecl **Indices, - unsigned NumIndices) - : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), - LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), - IsWritten(false), SourceOrderOrNumArrayIndices(NumIndices) -{ - std::uninitialized_copy(Indices, Indices + NumIndices, - getTrailingObjects<VarDecl *>()); -} - -CXXCtorInitializer *CXXCtorInitializer::Create(ASTContext &Context, - FieldDecl *Member, - SourceLocation MemberLoc, - SourceLocation L, Expr *Init, - SourceLocation R, - VarDecl **Indices, - unsigned NumIndices) { - void *Mem = Context.Allocate(totalSizeToAlloc<VarDecl *>(NumIndices), - llvm::alignOf<CXXCtorInitializer>()); - return new (Mem) CXXCtorInitializer(Context, Member, MemberLoc, L, Init, R, - Indices, NumIndices); -} - TypeLoc CXXCtorInitializer::getBaseClassLoc() const { if (isBaseInitializer()) return Initializee.get<TypeSourceInfo*>()->getTypeLoc(); @@ -2253,15 +2245,37 @@ SourceRange UsingDecl::getSourceRange() const { return SourceRange(Begin, getNameInfo().getEndLoc()); } +void UsingPackDecl::anchor() { } + +UsingPackDecl *UsingPackDecl::Create(ASTContext &C, DeclContext *DC, + NamedDecl *InstantiatedFrom, + ArrayRef<NamedDecl *> UsingDecls) { + size_t Extra = additionalSizeToAlloc<NamedDecl *>(UsingDecls.size()); + return new (C, DC, Extra) UsingPackDecl(DC, InstantiatedFrom, UsingDecls); +} + +UsingPackDecl *UsingPackDecl::CreateDeserialized(ASTContext &C, unsigned ID, + unsigned NumExpansions) { + size_t Extra = additionalSizeToAlloc<NamedDecl *>(NumExpansions); + auto *Result = new (C, ID, Extra) UsingPackDecl(nullptr, nullptr, None); + Result->NumExpansions = NumExpansions; + auto *Trail = Result->getTrailingObjects<NamedDecl *>(); + for (unsigned I = 0; I != NumExpansions; ++I) + new (Trail + I) NamedDecl*(nullptr); + return Result; +} + void UnresolvedUsingValueDecl::anchor() { } UnresolvedUsingValueDecl * UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, NestedNameSpecifierLoc QualifierLoc, - const DeclarationNameInfo &NameInfo) { + const DeclarationNameInfo &NameInfo, + SourceLocation EllipsisLoc) { return new (C, DC) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc, - QualifierLoc, NameInfo); + QualifierLoc, NameInfo, + EllipsisLoc); } UnresolvedUsingValueDecl * @@ -2269,7 +2283,8 @@ UnresolvedUsingValueDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) UnresolvedUsingValueDecl(nullptr, QualType(), SourceLocation(), NestedNameSpecifierLoc(), - DeclarationNameInfo()); + DeclarationNameInfo(), + SourceLocation()); } SourceRange UnresolvedUsingValueDecl::getSourceRange() const { @@ -2286,17 +2301,18 @@ UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation TypenameLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TargetNameLoc, - DeclarationName TargetName) { + DeclarationName TargetName, + SourceLocation EllipsisLoc) { return new (C, DC) UnresolvedUsingTypenameDecl( DC, UsingLoc, TypenameLoc, QualifierLoc, TargetNameLoc, - TargetName.getAsIdentifierInfo()); + TargetName.getAsIdentifierInfo(), EllipsisLoc); } UnresolvedUsingTypenameDecl * UnresolvedUsingTypenameDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) UnresolvedUsingTypenameDecl( nullptr, SourceLocation(), SourceLocation(), NestedNameSpecifierLoc(), - SourceLocation(), nullptr); + SourceLocation(), nullptr, SourceLocation()); } void StaticAssertDecl::anchor() { } @@ -2317,6 +2333,70 @@ StaticAssertDecl *StaticAssertDecl::CreateDeserialized(ASTContext &C, nullptr, SourceLocation(), false); } +void BindingDecl::anchor() {} + +BindingDecl *BindingDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation IdLoc, IdentifierInfo *Id) { + return new (C, DC) BindingDecl(DC, IdLoc, Id); +} + +BindingDecl *BindingDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) BindingDecl(nullptr, SourceLocation(), nullptr); +} + +VarDecl *BindingDecl::getHoldingVar() const { + Expr *B = getBinding(); + if (!B) + return nullptr; + auto *DRE = dyn_cast<DeclRefExpr>(B->IgnoreImplicit()); + if (!DRE) + return nullptr; + + auto *VD = dyn_cast<VarDecl>(DRE->getDecl()); + assert(VD->isImplicit() && "holding var for binding decl not implicit"); + return VD; +} + +void DecompositionDecl::anchor() {} + +DecompositionDecl *DecompositionDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, + SourceLocation LSquareLoc, + QualType T, TypeSourceInfo *TInfo, + StorageClass SC, + ArrayRef<BindingDecl *> Bindings) { + size_t Extra = additionalSizeToAlloc<BindingDecl *>(Bindings.size()); + return new (C, DC, Extra) + DecompositionDecl(C, DC, StartLoc, LSquareLoc, T, TInfo, SC, Bindings); +} + +DecompositionDecl *DecompositionDecl::CreateDeserialized(ASTContext &C, + unsigned ID, + unsigned NumBindings) { + size_t Extra = additionalSizeToAlloc<BindingDecl *>(NumBindings); + auto *Result = new (C, ID, Extra) + DecompositionDecl(C, nullptr, SourceLocation(), SourceLocation(), + QualType(), nullptr, StorageClass(), None); + // Set up and clean out the bindings array. + Result->NumBindings = NumBindings; + auto *Trail = Result->getTrailingObjects<BindingDecl *>(); + for (unsigned I = 0; I != NumBindings; ++I) + new (Trail + I) BindingDecl*(nullptr); + return Result; +} + +void DecompositionDecl::printName(llvm::raw_ostream &os) const { + os << '['; + bool Comma = false; + for (auto *B : bindings()) { + if (Comma) + os << ", "; + B->printName(os); + Comma = true; + } + os << ']'; +} + MSPropertyDecl *MSPropertyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, diff --git a/lib/AST/DeclGroup.cpp b/lib/AST/DeclGroup.cpp index f162e6d40c48e..2f95e1f1c345f 100644 --- a/lib/AST/DeclGroup.cpp +++ b/lib/AST/DeclGroup.cpp @@ -14,13 +14,12 @@ #include "clang/AST/DeclGroup.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" -#include "llvm/Support/Allocator.h" using namespace clang; DeclGroup* DeclGroup::Create(ASTContext &C, Decl **Decls, unsigned NumDecls) { assert(NumDecls > 1 && "Invalid DeclGroup"); unsigned Size = totalSizeToAlloc<Decl *>(NumDecls); - void* Mem = C.Allocate(Size, llvm::AlignOf<DeclGroup>::Alignment); + void *Mem = C.Allocate(Size, alignof(DeclGroup)); new (Mem) DeclGroup(NumDecls, Decls); return static_cast<DeclGroup*>(Mem); } diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index d2701211beae7..60d05f682e6e0 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -800,8 +800,7 @@ void ObjCMethodDecl::setParamsAndSelLocs(ASTContext &C, if (Params.empty() && SelLocs.empty()) return; - static_assert(llvm::AlignOf<ParmVarDecl *>::Alignment >= - llvm::AlignOf<SourceLocation>::Alignment, + static_assert(alignof(ParmVarDecl *) >= alignof(SourceLocation), "Alignment not sufficient for SourceLocation"); unsigned Size = sizeof(ParmVarDecl *) * NumParams + @@ -871,6 +870,12 @@ ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() { } } + // Ensure that the discovered method redeclaration has a valid declaration + // context. Used to prevent infinite loops when iterating redeclarations in + // a partially invalid AST. + if (Redecl && cast<Decl>(Redecl->getDeclContext())->isInvalidDecl()) + Redecl = nullptr; + if (!Redecl && isRedeclaration()) { // This is the last redeclaration, go back to the first method. return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(), @@ -897,9 +902,13 @@ ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() { return MD; } - if (isRedeclaration()) - return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(), - isInstanceMethod()); + if (isRedeclaration()) { + // It is possible that we have not done deserializing the ObjCMethod yet. + ObjCMethodDecl *MD = + cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(), + isInstanceMethod()); + return MD ? MD : this; + } return this; } @@ -1320,8 +1329,12 @@ ObjCTypeParamDecl *ObjCTypeParamDecl::Create(ASTContext &ctx, DeclContext *dc, IdentifierInfo *name, SourceLocation colonLoc, TypeSourceInfo *boundInfo) { - return new (ctx, dc) ObjCTypeParamDecl(ctx, dc, variance, varianceLoc, index, - nameLoc, name, colonLoc, boundInfo); + auto *TPDecl = + new (ctx, dc) ObjCTypeParamDecl(ctx, dc, variance, varianceLoc, index, + nameLoc, name, colonLoc, boundInfo); + QualType TPType = ctx.getObjCTypeParamType(TPDecl, {}); + TPDecl->setTypeForDecl(TPType.getTypePtr()); + return TPDecl; } ObjCTypeParamDecl *ObjCTypeParamDecl::CreateDeserialized(ASTContext &ctx, @@ -1366,7 +1379,7 @@ ObjCTypeParamList *ObjCTypeParamList::create( SourceLocation rAngleLoc) { void *mem = ctx.Allocate(totalSizeToAlloc<ObjCTypeParamDecl *>(typeParams.size()), - llvm::alignOf<ObjCTypeParamList>()); + alignof(ObjCTypeParamList)); return new (mem) ObjCTypeParamList(lAngleLoc, typeParams, rAngleLoc); } diff --git a/lib/AST/DeclOpenMP.cpp b/lib/AST/DeclOpenMP.cpp index 5b06ce0778a70..95e44acca032b 100644 --- a/lib/AST/DeclOpenMP.cpp +++ b/lib/AST/DeclOpenMP.cpp @@ -90,13 +90,18 @@ OMPDeclareReductionDecl::getPrevDeclInScope() const { void OMPCapturedExprDecl::anchor() {} OMPCapturedExprDecl *OMPCapturedExprDecl::Create(ASTContext &C, DeclContext *DC, - IdentifierInfo *Id, - QualType T) { - return new (C, DC) OMPCapturedExprDecl(C, DC, Id, T); + IdentifierInfo *Id, QualType T, + SourceLocation StartLoc) { + return new (C, DC) OMPCapturedExprDecl(C, DC, Id, T, StartLoc); } OMPCapturedExprDecl *OMPCapturedExprDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - return new (C, ID) OMPCapturedExprDecl(C, nullptr, nullptr, QualType()); + return new (C, ID) + OMPCapturedExprDecl(C, nullptr, nullptr, QualType(), SourceLocation()); } +SourceRange OMPCapturedExprDecl::getSourceRange() const { + assert(hasInit()); + return SourceRange(getInit()->getLocStart(), getInit()->getLocEnd()); +} diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 7e786990becb1..b8ebe1c568c79 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -78,6 +78,10 @@ namespace { void VisitTemplateDecl(const TemplateDecl *D); void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); void VisitClassTemplateDecl(ClassTemplateDecl *D); + void VisitClassTemplateSpecializationDecl( + ClassTemplateSpecializationDecl *D); + void VisitClassTemplatePartialSpecializationDecl( + ClassTemplatePartialSpecializationDecl *D); void VisitObjCMethodDecl(ObjCMethodDecl *D); void VisitObjCImplementationDecl(ObjCImplementationDecl *D); void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); @@ -95,8 +99,9 @@ namespace { void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D); void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D); - void PrintTemplateParameters(const TemplateParameterList *Params, - const TemplateArgumentList *Args = nullptr); + void printTemplateParameters(const TemplateParameterList *Params); + void printTemplateArguments(const TemplateArgumentList &Args, + const TemplateParameterList *Params = nullptr); void prettyPrintAttributes(Decl *D); void prettyPrintPragmas(Decl *D); void printDeclType(QualType T, StringRef DeclName, bool Pack = false); @@ -290,6 +295,13 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { if (D->isImplicit()) continue; + // Don't print implicit specializations, as they are printed when visiting + // corresponding templates. + if (auto FD = dyn_cast<FunctionDecl>(*D)) + if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation && + !isa<ClassTemplateSpecializationDecl>(DC)) + continue; + // The next bits of code handles stuff like "struct {int x;} a,b"; we're // forced to merge the declarations because there's no other way to // refer to the struct in question. This limited merging is safe without @@ -337,12 +349,19 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { const char *Terminator = nullptr; if (isa<OMPThreadPrivateDecl>(*D) || isa<OMPDeclareReductionDecl>(*D)) Terminator = nullptr; - else if (isa<FunctionDecl>(*D) && - cast<FunctionDecl>(*D)->isThisDeclarationADefinition()) + else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->hasBody()) Terminator = nullptr; - else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody()) - Terminator = nullptr; - else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) || + else if (auto FD = dyn_cast<FunctionDecl>(*D)) { + if (FD->isThisDeclarationADefinition()) + Terminator = nullptr; + else + Terminator = ";"; + } else if (auto TD = dyn_cast<FunctionTemplateDecl>(*D)) { + if (TD->getTemplatedDecl()->isThisDeclarationADefinition()) + Terminator = nullptr; + else + Terminator = ";"; + } else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) || isa<ObjCImplementationDecl>(*D) || isa<ObjCInterfaceDecl>(*D) || isa<ObjCProtocolDecl>(*D) || @@ -359,7 +378,14 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { if (Terminator) Out << Terminator; - Out << "\n"; + if (!Policy.TerseOutput && + ((isa<FunctionDecl>(*D) && + cast<FunctionDecl>(*D)->doesThisDeclarationHaveABody()) || + (isa<FunctionTemplateDecl>(*D) && + cast<FunctionTemplateDecl>(*D)->getTemplatedDecl()->doesThisDeclarationHaveABody()))) + ; // StmtPrinter already added '\n' after CompoundStmt. + else + Out << "\n"; // Declare target attribute is special one, natural spelling for the pragma // assumes "ending" construct so print it here. @@ -408,7 +434,7 @@ void DeclPrinter::VisitEnumDecl(EnumDecl *D) { } Out << *D; - if (D->isFixed()) + if (D->isFixed() && D->getASTContext().getLangOpts().CPlusPlus11) Out << " : " << D->getIntegerType().stream(Policy); if (D->isCompleteDefinition()) { @@ -449,6 +475,9 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { !D->isFunctionTemplateSpecialization()) prettyPrintPragmas(D); + if (D->isFunctionTemplateSpecialization()) + Out << "template<> "; + CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D); CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D); if (!Policy.SuppressSpecifiers) { @@ -473,6 +502,11 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { PrintingPolicy SubPolicy(Policy); SubPolicy.SuppressSpecifiers = false; std::string Proto = D->getNameInfo().getAsString(); + if (const TemplateArgumentList *TArgs = D->getTemplateSpecializationArgs()) { + llvm::raw_string_ostream POut(Proto); + DeclPrinter TArgPrinter(POut, SubPolicy, Indentation); + TArgPrinter.printTemplateArguments(*TArgs); + } QualType Ty = D->getType(); while (const ParenType *PT = dyn_cast<ParenType>(Ty)) { @@ -636,25 +670,29 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { Out << " = delete"; else if (D->isExplicitlyDefaulted()) Out << " = default"; - else if (D->doesThisDeclarationHaveABody() && !Policy.TerseOutput) { - if (!D->hasPrototype() && D->getNumParams()) { - // This is a K&R function definition, so we need to print the - // parameters. - Out << '\n'; - DeclPrinter ParamPrinter(Out, SubPolicy, Indentation); - Indentation += Policy.Indentation; - for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { - Indent(); - ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); - Out << ";\n"; - } - Indentation -= Policy.Indentation; - } else - Out << ' '; + else if (D->doesThisDeclarationHaveABody()) { + if (!Policy.TerseOutput) { + if (!D->hasPrototype() && D->getNumParams()) { + // This is a K&R function definition, so we need to print the + // parameters. + Out << '\n'; + DeclPrinter ParamPrinter(Out, SubPolicy, Indentation); + Indentation += Policy.Indentation; + for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { + Indent(); + ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); + Out << ";\n"; + } + Indentation -= Policy.Indentation; + } else + Out << ' '; - if (D->getBody()) - D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation); - Out << '\n'; + if (D->getBody()) + D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation); + } else { + if (isa<CXXConstructorDecl>(*D)) + Out << " {}"; + } } } @@ -662,7 +700,7 @@ void DeclPrinter::VisitFriendDecl(FriendDecl *D) { if (TypeSourceInfo *TSI = D->getFriendType()) { unsigned NumTPLists = D->getFriendTypeNumTemplateParameterLists(); for (unsigned i = 0; i < NumTPLists; ++i) - PrintTemplateParameters(D->getFriendTypeTemplateParameterList(i)); + printTemplateParameters(D->getFriendTypeTemplateParameterList(i)); Out << "friend "; Out << " " << TSI->getType().getAsString(Policy); } @@ -839,9 +877,15 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { prettyPrintAttributes(D); - if (D->getIdentifier()) + if (D->getIdentifier()) { Out << ' ' << *D; + if (auto S = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) + printTemplateArguments(S->getTemplateArgs(), S->getTemplateParameters()); + else if (auto S = dyn_cast<ClassTemplateSpecializationDecl>(D)) + printTemplateArguments(S->getTemplateArgs()); + } + if (D->isCompleteDefinition()) { // Print the base classes if (D->getNumBases()) { @@ -868,9 +912,13 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { // Print the class definition // FIXME: Doesn't print access specifiers, e.g., "public:" - Out << " {\n"; - VisitDeclContext(D); - Indent() << "}"; + if (Policy.TerseOutput) { + Out << " {}"; + } else { + Out << " {\n"; + VisitDeclContext(D); + Indent() << "}"; + } } } @@ -893,10 +941,8 @@ void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { Visit(*D->decls_begin()); } -void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params, - const TemplateArgumentList *Args) { +void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params) { assert(Params); - assert(!Args || Params->size() == Args->size()); Out << "template <"; @@ -905,8 +951,7 @@ void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params, Out << ", "; const Decl *Param = Params->getParam(i); - if (const TemplateTypeParmDecl *TTP = - dyn_cast<TemplateTypeParmDecl>(Param)) { + if (auto TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { if (TTP->wasDeclaredWithTypename()) Out << "typename "; @@ -918,30 +963,22 @@ void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params, Out << *TTP; - if (Args) { - Out << " = "; - Args->get(i).print(Policy, Out); - } else if (TTP->hasDefaultArgument()) { + if (TTP->hasDefaultArgument()) { Out << " = "; Out << TTP->getDefaultArgument().getAsString(Policy); }; - } else if (const NonTypeTemplateParmDecl *NTTP = - dyn_cast<NonTypeTemplateParmDecl>(Param)) { + } else if (auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) { StringRef Name; if (IdentifierInfo *II = NTTP->getIdentifier()) Name = II->getName(); printDeclType(NTTP->getType(), Name, NTTP->isParameterPack()); - if (Args) { - Out << " = "; - Args->get(i).print(Policy, Out); - } else if (NTTP->hasDefaultArgument()) { + if (NTTP->hasDefaultArgument()) { Out << " = "; NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy, Indentation); } - } else if (const TemplateTemplateParmDecl *TTPD = - dyn_cast<TemplateTemplateParmDecl>(Param)) { + } else if (auto TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) { VisitTemplateDecl(TTPD); // FIXME: print the default argument, if present. } @@ -950,8 +987,46 @@ void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params, Out << "> "; } +void DeclPrinter::printTemplateArguments(const TemplateArgumentList &Args, + const TemplateParameterList *Params) { + Out << "<"; + for (size_t I = 0, E = Args.size(); I < E; ++I) { + const TemplateArgument &A = Args[I]; + if (I) + Out << ", "; + if (Params) { + if (A.getKind() == TemplateArgument::Type) + if (auto T = A.getAsType()->getAs<TemplateTypeParmType>()) { + auto P = cast<TemplateTypeParmDecl>(Params->getParam(T->getIndex())); + Out << *P; + continue; + } + if (A.getKind() == TemplateArgument::Template) { + if (auto T = A.getAsTemplate().getAsTemplateDecl()) + if (auto TD = dyn_cast<TemplateTemplateParmDecl>(T)) { + auto P = cast<TemplateTemplateParmDecl>( + Params->getParam(TD->getIndex())); + Out << *P; + continue; + } + } + if (A.getKind() == TemplateArgument::Expression) { + if (auto E = dyn_cast<DeclRefExpr>(A.getAsExpr())) + if (auto N = dyn_cast<NonTypeTemplateParmDecl>(E->getDecl())) { + auto P = cast<NonTypeTemplateParmDecl>( + Params->getParam(N->getIndex())); + Out << *P; + continue; + } + } + } + A.print(Policy, Out); + } + Out << ">"; +} + void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) { - PrintTemplateParameters(D->getTemplateParameters()); + printTemplateParameters(D->getTemplateParameters()); if (const TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) { @@ -965,30 +1040,49 @@ void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) { } void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { + prettyPrintPragmas(D->getTemplatedDecl()); + VisitRedeclarableTemplateDecl(D); + if (PrintInstantiation) { - TemplateParameterList *Params = D->getTemplateParameters(); - for (auto *I : D->specializations()) { - prettyPrintPragmas(I); - PrintTemplateParameters(Params, I->getTemplateSpecializationArgs()); - Visit(I); - } + FunctionDecl *PrevDecl = D->getTemplatedDecl(); + const FunctionDecl *Def; + if (PrevDecl->isDefined(Def) && Def != PrevDecl) + return; + for (auto *I : D->specializations()) + if (I->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) { + if (!PrevDecl->isThisDeclarationADefinition()) + Out << ";\n"; + Indent(); + prettyPrintPragmas(I); + Visit(I); + } } - - prettyPrintPragmas(D->getTemplatedDecl()); - return VisitRedeclarableTemplateDecl(D); } void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) { + VisitRedeclarableTemplateDecl(D); + if (PrintInstantiation) { - TemplateParameterList *Params = D->getTemplateParameters(); - for (auto *I : D->specializations()) { - PrintTemplateParameters(Params, &I->getTemplateArgs()); - Visit(I); - Out << '\n'; - } + for (auto *I : D->specializations()) + if (I->getSpecializationKind() == TSK_ImplicitInstantiation) { + if (D->isThisDeclarationADefinition()) + Out << ";"; + Out << "\n"; + Visit(I); + } } +} + +void DeclPrinter::VisitClassTemplateSpecializationDecl( + ClassTemplateSpecializationDecl *D) { + Out << "template<> "; + VisitCXXRecordDecl(D); +} - return VisitRedeclarableTemplateDecl(D); +void DeclPrinter::VisitClassTemplatePartialSpecializationDecl( + ClassTemplatePartialSpecializationDecl *D) { + printTemplateParameters(D->getTemplateParameters()); + VisitCXXRecordDecl(D); } //---------------------------------------------------------------------------- @@ -1346,6 +1440,17 @@ void DeclPrinter::VisitUsingDecl(UsingDecl *D) { if (D->hasTypename()) Out << "typename "; D->getQualifier()->print(Out, Policy); + + // Use the correct record name when the using declaration is used for + // inheriting constructors. + for (const auto *Shadow : D->shadows()) { + if (const auto *ConstructorShadow = + dyn_cast<ConstructorUsingShadowDecl>(Shadow)) { + assert(Shadow->getDeclContext() == ConstructorShadow->getDeclContext()); + Out << *ConstructorShadow->getNominatedBaseClass(); + return; + } + } Out << *D; } diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 37943cdd5b7b3..8643cbfcd960a 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -31,10 +31,11 @@ using namespace clang; TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef<NamedDecl *> Params, - SourceLocation RAngleLoc) + SourceLocation RAngleLoc, + Expr *RequiresClause) : TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc), - NumParams(Params.size()), ContainsUnexpandedParameterPack(false) { - assert(this->NumParams == NumParams && "Too many template parameters"); + NumParams(Params.size()), ContainsUnexpandedParameterPack(false), + HasRequiresClause(static_cast<bool>(RequiresClause)) { for (unsigned Idx = 0; Idx < NumParams; ++Idx) { NamedDecl *P = Params[Idx]; begin()[Idx] = P; @@ -52,15 +53,21 @@ TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc, // template parameter list does too. } } + if (RequiresClause) { + *getTrailingObjects<Expr *>() = RequiresClause; + } } -TemplateParameterList *TemplateParameterList::Create( - const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, - ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc) { - void *Mem = C.Allocate(totalSizeToAlloc<NamedDecl *>(Params.size()), - llvm::alignOf<TemplateParameterList>()); +TemplateParameterList * +TemplateParameterList::Create(const ASTContext &C, SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + ArrayRef<NamedDecl *> Params, + SourceLocation RAngleLoc, Expr *RequiresClause) { + void *Mem = C.Allocate(totalSizeToAlloc<NamedDecl *, Expr *>( + Params.size(), RequiresClause ? 1u : 0u), + alignof(TemplateParameterList)); return new (Mem) TemplateParameterList(TemplateLoc, LAngleLoc, Params, - RAngleLoc); + RAngleLoc, RequiresClause); } unsigned TemplateParameterList::getMinRequiredArguments() const { @@ -197,44 +204,6 @@ void RedeclarableTemplateDecl::addSpecializationImpl( SETraits::getDecl(Entry)); } -/// \brief Generate the injected template arguments for the given template -/// parameter list, e.g., for the injected-class-name of a class template. -static void GenerateInjectedTemplateArgs(ASTContext &Context, - TemplateParameterList *Params, - TemplateArgument *Args) { - for (NamedDecl *Param : *Params) { - TemplateArgument Arg; - if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { - QualType ArgType = Context.getTypeDeclType(TTP); - if (TTP->isParameterPack()) - ArgType = Context.getPackExpansionType(ArgType, None); - - Arg = TemplateArgument(ArgType); - } else if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) { - Expr *E = new (Context) DeclRefExpr(NTTP, /*enclosing*/ false, - NTTP->getType().getNonLValueExprType(Context), - Expr::getValueKindForType(NTTP->getType()), - NTTP->getLocation()); - - if (NTTP->isParameterPack()) - E = new (Context) PackExpansionExpr(Context.DependentTy, E, - NTTP->getLocation(), None); - Arg = TemplateArgument(E); - } else { - auto *TTP = cast<TemplateTemplateParmDecl>(Param); - if (TTP->isParameterPack()) - Arg = TemplateArgument(TemplateName(TTP), Optional<unsigned>()); - else - Arg = TemplateArgument(TemplateName(TTP)); - } - - if (Param->isTemplateParameterPack()) - Arg = TemplateArgument::CreatePackCopy(Context, Arg); - - *Args++ = Arg; - } -} - //===----------------------------------------------------------------------===// // FunctionTemplateDecl Implementation //===----------------------------------------------------------------------===// @@ -303,10 +272,13 @@ ArrayRef<TemplateArgument> FunctionTemplateDecl::getInjectedTemplateArgs() { TemplateParameterList *Params = getTemplateParameters(); Common *CommonPtr = getCommonPtr(); if (!CommonPtr->InjectedArgs) { - CommonPtr->InjectedArgs - = new (getASTContext()) TemplateArgument[Params->size()]; - GenerateInjectedTemplateArgs(getASTContext(), Params, - CommonPtr->InjectedArgs); + auto &Context = getASTContext(); + SmallVector<TemplateArgument, 16> TemplateArgs; + Context.getInjectedTemplateArgs(Params, TemplateArgs); + CommonPtr->InjectedArgs = + new (Context) TemplateArgument[TemplateArgs.size()]; + std::copy(TemplateArgs.begin(), TemplateArgs.end(), + CommonPtr->InjectedArgs); } return llvm::makeArrayRef(CommonPtr->InjectedArgs, Params->size()); @@ -457,8 +429,7 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() { ASTContext &Context = getASTContext(); TemplateParameterList *Params = getTemplateParameters(); SmallVector<TemplateArgument, 16> TemplateArgs; - TemplateArgs.resize(Params->size()); - GenerateInjectedTemplateArgs(getASTContext(), Params, TemplateArgs.data()); + Context.getInjectedTemplateArgs(Params, TemplateArgs); CommonPtr->InjectedClassNameType = Context.getTemplateSpecializationType(TemplateName(this), TemplateArgs); @@ -754,9 +725,16 @@ void ClassTemplateSpecializationDecl::getNameForDiagnostic( raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const { NamedDecl::getNameForDiagnostic(OS, Policy, Qualified); - const TemplateArgumentList &TemplateArgs = getTemplateArgs(); - TemplateSpecializationType::PrintTemplateArgumentList( - OS, TemplateArgs.asArray(), Policy); + auto *PS = dyn_cast<ClassTemplatePartialSpecializationDecl>(this); + if (const ASTTemplateArgumentListInfo *ArgsAsWritten = + PS ? PS->getTemplateArgsAsWritten() : nullptr) { + TemplateSpecializationType::PrintTemplateArgumentList( + OS, ArgsAsWritten->arguments(), Policy); + } else { + const TemplateArgumentList &TemplateArgs = getTemplateArgs(); + TemplateSpecializationType::PrintTemplateArgumentList( + OS, TemplateArgs.asArray(), Policy); + } } ClassTemplateDecl * @@ -1086,9 +1064,16 @@ void VarTemplateSpecializationDecl::getNameForDiagnostic( raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const { NamedDecl::getNameForDiagnostic(OS, Policy, Qualified); - const TemplateArgumentList &TemplateArgs = getTemplateArgs(); - TemplateSpecializationType::PrintTemplateArgumentList( - OS, TemplateArgs.asArray(), Policy); + auto *PS = dyn_cast<VarTemplatePartialSpecializationDecl>(this); + if (const ASTTemplateArgumentListInfo *ArgsAsWritten = + PS ? PS->getTemplateArgsAsWritten() : nullptr) { + TemplateSpecializationType::PrintTemplateArgumentList( + OS, ArgsAsWritten->arguments(), Policy); + } else { + const TemplateArgumentList &TemplateArgs = getTemplateArgs(); + TemplateSpecializationType::PrintTemplateArgumentList( + OS, TemplateArgs.asArray(), Policy); + } } VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const { @@ -1169,7 +1154,7 @@ createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) { // <typename T, T ...Ints> NamedDecl *P[2] = {T, N}; auto *TPL = TemplateParameterList::Create( - C, SourceLocation(), SourceLocation(), P, SourceLocation()); + C, SourceLocation(), SourceLocation(), P, SourceLocation(), nullptr); // template <typename T, ...Ints> class IntSeq auto *TemplateTemplateParm = TemplateTemplateParmDecl::Create( @@ -1194,7 +1179,7 @@ createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) { // template <template <typename T, T ...Ints> class IntSeq, typename T, T N> return TemplateParameterList::Create(C, SourceLocation(), SourceLocation(), - Params, SourceLocation()); + Params, SourceLocation(), nullptr); } static TemplateParameterList * @@ -1215,7 +1200,7 @@ createTypePackElementParameterList(const ASTContext &C, DeclContext *DC) { NamedDecl *Params[] = {Index, Ts}; return TemplateParameterList::Create(C, SourceLocation(), SourceLocation(), llvm::makeArrayRef(Params), - SourceLocation()); + SourceLocation(), nullptr); } static TemplateParameterList *createBuiltinTemplateParameterList( diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp index 2a988e1d22d03..52791e51d2dc1 100644 --- a/lib/AST/DeclarationName.cpp +++ b/lib/AST/DeclarationName.cpp @@ -11,14 +11,13 @@ // classes. // //===----------------------------------------------------------------------===// +#include "clang/AST/DeclarationName.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclarationName.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeOrdering.h" #include "clang/Basic/IdentifierTable.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -96,12 +95,18 @@ int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) { case DeclarationName::ObjCMultiArgSelector: { Selector LHSSelector = LHS.getObjCSelector(); Selector RHSSelector = RHS.getObjCSelector(); + // getNumArgs for ZeroArgSelector returns 0, but we still need to compare. + if (LHS.getNameKind() == DeclarationName::ObjCZeroArgSelector && + RHS.getNameKind() == DeclarationName::ObjCZeroArgSelector) { + return LHSSelector.getAsIdentifierInfo()->getName().compare( + RHSSelector.getAsIdentifierInfo()->getName()); + } unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs(); for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) { switch (LHSSelector.getNameForSlot(I).compare( RHSSelector.getNameForSlot(I))) { - case -1: return true; - case 1: return false; + case -1: return -1; + case 1: return 1; default: break; } } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 091e8787d8b6d..93f3ad5f2bdd5 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" @@ -36,9 +35,33 @@ #include <cstring> using namespace clang; -const CXXRecordDecl *Expr::getBestDynamicClassType() const { - const Expr *E = ignoreParenBaseCasts(); +const Expr *Expr::getBestDynamicClassTypeExpr() const { + const Expr *E = this; + while (true) { + E = E->ignoreParenBaseCasts(); + + // Follow the RHS of a comma operator. + if (auto *BO = dyn_cast<BinaryOperator>(E)) { + if (BO->getOpcode() == BO_Comma) { + E = BO->getRHS(); + continue; + } + } + + // Step into initializer for materialized temporaries. + if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) { + E = MTE->GetTemporaryExpr(); + continue; + } + + break; + } + + return E; +} +const CXXRecordDecl *Expr::getBestDynamicClassType() const { + const Expr *E = getBestDynamicClassTypeExpr(); QualType DerivedType = E->getType(); if (const PointerType *PTy = DerivedType->getAs<PointerType>()) DerivedType = PTy->getPointeeType(); @@ -403,7 +426,7 @@ DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context, HasTemplateKWAndArgsInfo ? 1 : 0, TemplateArgs ? TemplateArgs->size() : 0); - void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>()); + void *Mem = Context.Allocate(Size, alignof(DeclRefExpr)); return new (Mem) DeclRefExpr(Context, QualifierLoc, TemplateKWLoc, D, RefersToEnclosingVariableOrCapture, NameInfo, FoundD, TemplateArgs, T, VK); @@ -420,7 +443,7 @@ DeclRefExpr *DeclRefExpr::CreateEmpty(const ASTContext &Context, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( HasQualifier ? 1 : 0, HasFoundDecl ? 1 : 0, HasTemplateKWAndArgsInfo, NumTemplateArgs); - void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>()); + void *Mem = Context.Allocate(Size, alignof(DeclRefExpr)); return new (Mem) DeclRefExpr(EmptyShell()); } @@ -495,20 +518,21 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { } return ""; } - if (auto *BD = dyn_cast<BlockDecl>(CurrentDecl)) { - std::unique_ptr<MangleContext> MC; - MC.reset(Context.createMangleContext()); - SmallString<256> Buffer; - llvm::raw_svector_ostream Out(Buffer); + if (isa<BlockDecl>(CurrentDecl)) { + // For blocks we only emit something if it is enclosed in a function + // For top-level block we'd like to include the name of variable, but we + // don't have it at this point. auto DC = CurrentDecl->getDeclContext(); if (DC->isFileContext()) - MC->mangleGlobalBlock(BD, /*ID*/ nullptr, Out); - else if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC)) - MC->mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, Out); - else if (const auto *DD = dyn_cast<CXXDestructorDecl>(DC)) - MC->mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, Out); - else - MC->mangleBlock(DC, BD, Out); + return ""; + + SmallString<256> Buffer; + llvm::raw_svector_ostream Out(Buffer); + if (auto *DCBlock = dyn_cast<BlockDecl>(DC)) + // For nested blocks, propagate up to the parent. + Out << ComputeName(IT, DCBlock); + else if (auto *DCDecl = dyn_cast<Decl>(DC)) + Out << ComputeName(IT, DCDecl) << "_block_invoke"; return Out.str(); } if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) { @@ -538,12 +562,14 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { FT = dyn_cast<FunctionProtoType>(AFT); if (IT == FuncSig) { + assert(FT && "We must have a written prototype in this case."); switch (FT->getCallConv()) { case CC_C: POut << "__cdecl "; break; case CC_X86StdCall: POut << "__stdcall "; break; case CC_X86FastCall: POut << "__fastcall "; break; case CC_X86ThisCall: POut << "__thiscall "; break; case CC_X86VectorCall: POut << "__vectorcall "; break; + case CC_X86RegCall: POut << "__regcall "; break; // Only bother printing the conventions that MSVC knows about. default: break; } @@ -756,33 +782,33 @@ FloatingLiteral::Create(const ASTContext &C, EmptyShell Empty) { const llvm::fltSemantics &FloatingLiteral::getSemantics() const { switch(FloatingLiteralBits.Semantics) { case IEEEhalf: - return llvm::APFloat::IEEEhalf; + return llvm::APFloat::IEEEhalf(); case IEEEsingle: - return llvm::APFloat::IEEEsingle; + return llvm::APFloat::IEEEsingle(); case IEEEdouble: - return llvm::APFloat::IEEEdouble; + return llvm::APFloat::IEEEdouble(); case x87DoubleExtended: - return llvm::APFloat::x87DoubleExtended; + return llvm::APFloat::x87DoubleExtended(); case IEEEquad: - return llvm::APFloat::IEEEquad; + return llvm::APFloat::IEEEquad(); case PPCDoubleDouble: - return llvm::APFloat::PPCDoubleDouble; + return llvm::APFloat::PPCDoubleDouble(); } llvm_unreachable("Unrecognised floating semantics"); } void FloatingLiteral::setSemantics(const llvm::fltSemantics &Sem) { - if (&Sem == &llvm::APFloat::IEEEhalf) + if (&Sem == &llvm::APFloat::IEEEhalf()) FloatingLiteralBits.Semantics = IEEEhalf; - else if (&Sem == &llvm::APFloat::IEEEsingle) + else if (&Sem == &llvm::APFloat::IEEEsingle()) FloatingLiteralBits.Semantics = IEEEsingle; - else if (&Sem == &llvm::APFloat::IEEEdouble) + else if (&Sem == &llvm::APFloat::IEEEdouble()) FloatingLiteralBits.Semantics = IEEEdouble; - else if (&Sem == &llvm::APFloat::x87DoubleExtended) + else if (&Sem == &llvm::APFloat::x87DoubleExtended()) FloatingLiteralBits.Semantics = x87DoubleExtended; - else if (&Sem == &llvm::APFloat::IEEEquad) + else if (&Sem == &llvm::APFloat::IEEEquad()) FloatingLiteralBits.Semantics = IEEEquad; - else if (&Sem == &llvm::APFloat::PPCDoubleDouble) + else if (&Sem == &llvm::APFloat::PPCDoubleDouble()) FloatingLiteralBits.Semantics = PPCDoubleDouble; else llvm_unreachable("Unknown floating semantics"); @@ -794,7 +820,7 @@ void FloatingLiteral::setSemantics(const llvm::fltSemantics &Sem) { double FloatingLiteral::getValueAsApproximateDouble() const { llvm::APFloat V = getValue(); bool ignored; - V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven, + V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven, &ignored); return V.convertToDouble(); } @@ -832,9 +858,9 @@ StringLiteral *StringLiteral::Create(const ASTContext &C, StringRef Str, // Allocate enough space for the StringLiteral plus an array of locations for // any concatenated string tokens. - void *Mem = C.Allocate(sizeof(StringLiteral)+ - sizeof(SourceLocation)*(NumStrs-1), - llvm::alignOf<StringLiteral>()); + void *Mem = + C.Allocate(sizeof(StringLiteral) + sizeof(SourceLocation) * (NumStrs - 1), + alignof(StringLiteral)); StringLiteral *SL = new (Mem) StringLiteral(Ty); // OPTIMIZE: could allocate this appended to the StringLiteral. @@ -850,9 +876,9 @@ StringLiteral *StringLiteral::Create(const ASTContext &C, StringRef Str, StringLiteral *StringLiteral::CreateEmpty(const ASTContext &C, unsigned NumStrs) { - void *Mem = C.Allocate(sizeof(StringLiteral)+ - sizeof(SourceLocation)*(NumStrs-1), - llvm::alignOf<StringLiteral>()); + void *Mem = + C.Allocate(sizeof(StringLiteral) + sizeof(SourceLocation) * (NumStrs - 1), + alignof(StringLiteral)); StringLiteral *SL = new (Mem) StringLiteral(QualType()); SL->CharByteWidth = 0; SL->Length = 0; @@ -944,10 +970,13 @@ void StringLiteral::outputString(raw_ostream &OS) const { // Handle some common non-printable cases to make dumps prettier. case '\\': OS << "\\\\"; break; case '"': OS << "\\\""; break; - case '\n': OS << "\\n"; break; - case '\t': OS << "\\t"; break; case '\a': OS << "\\a"; break; case '\b': OS << "\\b"; break; + case '\f': OS << "\\f"; break; + case '\n': OS << "\\n"; break; + case '\r': OS << "\\r"; break; + case '\t': OS << "\\t"; break; + case '\v': OS << "\\v"; break; } } OS << '"'; @@ -1182,8 +1211,16 @@ void CallExpr::updateDependenciesFromArg(Expr *Arg) { ExprBits.ContainsUnexpandedParameterPack = true; } +FunctionDecl *CallExpr::getDirectCallee() { + return dyn_cast_or_null<FunctionDecl>(getCalleeDecl()); +} + Decl *CallExpr::getCalleeDecl() { - Expr *CEE = getCallee()->IgnoreParenImpCasts(); + return getCallee()->getReferencedDeclOfCallee(); +} + +Decl *Expr::getReferencedDeclOfCallee() { + Expr *CEE = IgnoreParenImpCasts(); while (SubstNonTypeTemplateParmExpr *NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(CEE)) { @@ -1206,10 +1243,6 @@ Decl *CallExpr::getCalleeDecl() { return nullptr; } -FunctionDecl *CallExpr::getDirectCallee() { - return dyn_cast_or_null<FunctionDecl>(getCalleeDecl()); -} - /// setNumArgs - This changes the number of arguments present in this call. /// Any orphaned expressions are deleted by this, and any new operands are set /// to null. @@ -1417,7 +1450,7 @@ MemberExpr *MemberExpr::Create( HasTemplateKWAndArgsInfo ? 1 : 0, targs ? targs->size() : 0); - void *Mem = C.Allocate(Size, llvm::alignOf<MemberExpr>()); + void *Mem = C.Allocate(Size, alignof(MemberExpr)); MemberExpr *E = new (Mem) MemberExpr(base, isarrow, OperatorLoc, memberdecl, nameinfo, ty, vk, ok); @@ -1570,6 +1603,8 @@ bool CastExpr::CastConsistency() const { case CK_ARCReclaimReturnedObject: case CK_ARCExtendBlockObject: case CK_ZeroToOCLEvent: + case CK_ZeroToOCLQueue: + case CK_IntToOCLSampler: assert(!getType()->isBooleanType() && "unheralded conversion to bool"); goto CheckNoBasePath; @@ -1830,6 +1865,24 @@ bool InitListExpr::isStringLiteralInit() const { return isa<StringLiteral>(Init) || isa<ObjCEncodeExpr>(Init); } +bool InitListExpr::isTransparent() const { + assert(isSemanticForm() && "syntactic form never semantically transparent"); + + // A glvalue InitListExpr is always just sugar. + if (isGLValue()) { + assert(getNumInits() == 1 && "multiple inits in glvalue init list"); + return true; + } + + // Otherwise, we're sugar if and only if we have exactly one initializer that + // is of the same type. + if (getNumInits() != 1 || !getInit(0)) + return false; + + return getType().getCanonicalType() == + getInit(0)->getType().getCanonicalType(); +} + SourceLocation InitListExpr::getLocStart() const { if (InitListExpr *SyntacticForm = getSyntacticForm()) return SyntacticForm->getLocStart(); @@ -2212,12 +2265,15 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, // effects (e.g. a placement new with an uninitialized POD). case CXXDeleteExprClass: return false; + case MaterializeTemporaryExprClass: + return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr() + ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); case CXXBindTemporaryExprClass: - return (cast<CXXBindTemporaryExpr>(this) - ->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx)); + return cast<CXXBindTemporaryExpr>(this)->getSubExpr() + ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); case ExprWithCleanupsClass: - return (cast<ExprWithCleanups>(this) - ->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx)); + return cast<ExprWithCleanups>(this)->getSubExpr() + ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); } } @@ -2748,7 +2804,8 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, CE->getCastKind() == CK_ToUnion || CE->getCastKind() == CK_ConstructorConversion || CE->getCastKind() == CK_NonAtomicToAtomic || - CE->getCastKind() == CK_AtomicToNonAtomic) + CE->getCastKind() == CK_AtomicToNonAtomic || + CE->getCastKind() == CK_IntToOCLSampler) return CE->getSubExpr()->isConstantInitializer(Ctx, false, Culprit); break; @@ -2843,6 +2900,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case UnaryExprOrTypeTraitExprClass: case AddrLabelExprClass: case GNUNullExprClass: + case ArrayInitIndexExprClass: case NoInitExprClass: case CXXBoolLiteralExprClass: case CXXNullPtrLiteralExprClass: @@ -2919,6 +2977,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case ExtVectorElementExprClass: case DesignatedInitExprClass: case DesignatedInitUpdateExprClass: + case ArrayInitLoopExprClass: case ParenListExprClass: case CXXPseudoDestructorExprClass: case CXXStdInitializerListExprClass: @@ -3307,11 +3366,16 @@ FieldDecl *Expr::getSourceBitField() { if (Ivar->isBitField()) return Ivar; - if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E)) + if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E)) { if (FieldDecl *Field = dyn_cast<FieldDecl>(DeclRef->getDecl())) if (Field->isBitField()) return Field; + if (BindingDecl *BD = dyn_cast<BindingDecl>(DeclRef->getDecl())) + if (Expr *E = BD->getBinding()) + return E->getSourceBitField(); + } + if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(E)) { if (BinOp->isAssignmentOp() && BinOp->getLHS()) return BinOp->getLHS()->getSourceBitField(); @@ -3328,6 +3392,7 @@ FieldDecl *Expr::getSourceBitField() { } bool Expr::refersToVectorElement() const { + // FIXME: Why do we not just look at the ObjectKind here? const Expr *E = this->IgnoreParens(); while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { @@ -3344,6 +3409,11 @@ bool Expr::refersToVectorElement() const { if (isa<ExtVectorElementExpr>(E)) return true; + if (auto *DRE = dyn_cast<DeclRefExpr>(E)) + if (auto *BD = dyn_cast<BindingDecl>(DRE->getDecl())) + if (auto *E = BD->getBinding()) + return E->refersToVectorElement(); + return false; } @@ -3396,8 +3466,11 @@ bool ExtVectorElementExpr::containsDuplicateElements() const { void ExtVectorElementExpr::getEncodedElementAccess( SmallVectorImpl<uint32_t> &Elts) const { StringRef Comp = Accessor->getName(); - if (Comp[0] == 's' || Comp[0] == 'S') + bool isNumericAccessor = false; + if (Comp[0] == 's' || Comp[0] == 'S') { Comp = Comp.substr(1); + isNumericAccessor = true; + } bool isHi = Comp == "hi"; bool isLo = Comp == "lo"; @@ -3416,7 +3489,7 @@ void ExtVectorElementExpr::getEncodedElementAccess( else if (isOdd) Index = 2 * i + 1; else - Index = ExtVectorType::getAccessorIdx(Comp[i]); + Index = ExtVectorType::getAccessorIdx(Comp[i], isNumericAccessor); Elts.push_back(Index); } @@ -3589,7 +3662,7 @@ DesignatedInitExpr::Create(const ASTContext &C, SourceLocation ColonOrEqualLoc, bool UsesColonSyntax, Expr *Init) { void *Mem = C.Allocate(totalSizeToAlloc<Stmt *>(IndexExprs.size() + 1), - llvm::alignOf<DesignatedInitExpr>()); + alignof(DesignatedInitExpr)); return new (Mem) DesignatedInitExpr(C, C.VoidTy, Designators, ColonOrEqualLoc, UsesColonSyntax, IndexExprs, Init); @@ -3598,7 +3671,7 @@ DesignatedInitExpr::Create(const ASTContext &C, DesignatedInitExpr *DesignatedInitExpr::CreateEmpty(const ASTContext &C, unsigned NumIndexExprs) { void *Mem = C.Allocate(totalSizeToAlloc<Stmt *>(NumIndexExprs + 1), - llvm::alignOf<DesignatedInitExpr>()); + alignof(DesignatedInitExpr)); return new (Mem) DesignatedInitExpr(NumIndexExprs + 1); } @@ -3738,7 +3811,7 @@ PseudoObjectExpr *PseudoObjectExpr::Create(const ASTContext &Context, unsigned numSemanticExprs) { void *buffer = Context.Allocate(totalSizeToAlloc<Expr *>(1 + numSemanticExprs), - llvm::alignOf<PseudoObjectExpr>()); + alignof(PseudoObjectExpr)); return new(buffer) PseudoObjectExpr(sh, numSemanticExprs); } @@ -3766,7 +3839,7 @@ PseudoObjectExpr *PseudoObjectExpr::Create(const ASTContext &C, Expr *syntax, } void *buffer = C.Allocate(totalSizeToAlloc<Expr *>(semantics.size() + 1), - llvm::alignOf<PseudoObjectExpr>()); + alignof(PseudoObjectExpr)); return new(buffer) PseudoObjectExpr(type, VK, syntax, semantics, resultIndex); } diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index a13033d47467f..ad510e0070e63 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -25,6 +25,22 @@ using namespace clang; // Child Iterators for iterating over subexpressions/substatements //===----------------------------------------------------------------------===// +bool CXXOperatorCallExpr::isInfixBinaryOp() const { + // An infix binary operator is any operator with two arguments other than + // operator() and operator[]. Note that none of these operators can have + // default arguments, so it suffices to check the number of argument + // expressions. + if (getNumArgs() != 2) + return false; + + switch (getOperator()) { + case OO_Call: case OO_Subscript: + return false; + default: + return true; + } +} + bool CXXTypeidExpr::isPotentiallyEvaluated() const { if (isTypeOperand()) return false; @@ -62,7 +78,7 @@ SourceLocation CXXScalarValueInitExpr::getLocStart() const { // CXXNewExpr CXXNewExpr::CXXNewExpr(const ASTContext &C, bool globalNew, FunctionDecl *operatorNew, FunctionDecl *operatorDelete, - bool usualArrayDeleteWantsSize, + bool PassAlignment, bool usualArrayDeleteWantsSize, ArrayRef<Expr*> placementArgs, SourceRange typeIdParens, Expr *arraySize, InitializationStyle initializationStyle, @@ -76,7 +92,8 @@ CXXNewExpr::CXXNewExpr(const ASTContext &C, bool globalNew, SubExprs(nullptr), OperatorNew(operatorNew), OperatorDelete(operatorDelete), AllocatedTypeInfo(allocatedTypeInfo), TypeIdParens(typeIdParens), Range(Range), DirectInitRange(directInitRange), - GlobalNew(globalNew), UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) { + GlobalNew(globalNew), PassAlignment(PassAlignment), + UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) { assert((initializer != nullptr || initializationStyle == NoInit) && "Only NoInit can have no initializer."); StoredInitializationStyle = initializer ? initializationStyle + 1 : 0; @@ -226,7 +243,7 @@ UnresolvedLookupExpr::Create(const ASTContext &C, std::size_t Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(1, num_args); - void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedLookupExpr>()); + void *Mem = C.Allocate(Size, alignof(UnresolvedLookupExpr)); return new (Mem) UnresolvedLookupExpr(C, NamingClass, QualifierLoc, TemplateKWLoc, NameInfo, ADL, /*Overload*/ true, Args, @@ -241,7 +258,7 @@ UnresolvedLookupExpr::CreateEmpty(const ASTContext &C, std::size_t Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( HasTemplateKWAndArgsInfo, NumTemplateArgs); - void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedLookupExpr>()); + void *Mem = C.Allocate(Size, alignof(UnresolvedLookupExpr)); UnresolvedLookupExpr *E = new (Mem) UnresolvedLookupExpr(EmptyShell()); E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo; return E; @@ -284,9 +301,8 @@ OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C, } } - Results = static_cast<DeclAccessPair *>( - C.Allocate(sizeof(DeclAccessPair) * NumResults, - llvm::alignOf<DeclAccessPair>())); + Results = static_cast<DeclAccessPair *>(C.Allocate( + sizeof(DeclAccessPair) * NumResults, alignof(DeclAccessPair))); memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair)); } @@ -323,11 +339,11 @@ void OverloadExpr::initializeResults(const ASTContext &C, assert(!Results && "Results already initialized!"); NumResults = End - Begin; if (NumResults) { - Results = static_cast<DeclAccessPair *>( - C.Allocate(sizeof(DeclAccessPair) * NumResults, - - llvm::alignOf<DeclAccessPair>())); - memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair)); + Results = static_cast<DeclAccessPair *>( + C.Allocate(sizeof(DeclAccessPair) * NumResults, + + alignof(DeclAccessPair))); + memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair)); } } @@ -853,8 +869,6 @@ LambdaExpr::LambdaExpr(QualType T, SourceRange IntroducerRange, SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures, bool ExplicitParams, bool ExplicitResultType, ArrayRef<Expr *> CaptureInits, - ArrayRef<VarDecl *> ArrayIndexVars, - ArrayRef<unsigned> ArrayIndexStarts, SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack) : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary, T->isDependentType(), @@ -891,17 +905,6 @@ LambdaExpr::LambdaExpr(QualType T, SourceRange IntroducerRange, // Copy the body of the lambda. *Stored++ = getCallOperator()->getBody(); - - // Copy the array index variables, if any. - HasArrayIndexVars = !ArrayIndexVars.empty(); - if (HasArrayIndexVars) { - assert(ArrayIndexStarts.size() == NumCaptures); - memcpy(getArrayIndexVars(), ArrayIndexVars.data(), - sizeof(VarDecl *) * ArrayIndexVars.size()); - memcpy(getArrayIndexStarts(), ArrayIndexStarts.data(), - sizeof(unsigned) * Captures.size()); - getArrayIndexStarts()[Captures.size()] = ArrayIndexVars.size(); - } } LambdaExpr *LambdaExpr::Create( @@ -909,31 +912,24 @@ LambdaExpr *LambdaExpr::Create( SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures, bool ExplicitParams, bool ExplicitResultType, ArrayRef<Expr *> CaptureInits, - ArrayRef<VarDecl *> ArrayIndexVars, ArrayRef<unsigned> ArrayIndexStarts, SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack) { // Determine the type of the expression (i.e., the type of the // function object we're creating). QualType T = Context.getTypeDeclType(Class); - unsigned Size = totalSizeToAlloc<Stmt *, unsigned, VarDecl *>( - Captures.size() + 1, ArrayIndexVars.empty() ? 0 : Captures.size() + 1, - ArrayIndexVars.size()); + unsigned Size = totalSizeToAlloc<Stmt *>(Captures.size() + 1); void *Mem = Context.Allocate(Size); - return new (Mem) LambdaExpr(T, IntroducerRange, - CaptureDefault, CaptureDefaultLoc, Captures, - ExplicitParams, ExplicitResultType, - CaptureInits, ArrayIndexVars, ArrayIndexStarts, - ClosingBrace, ContainsUnexpandedParameterPack); + return new (Mem) + LambdaExpr(T, IntroducerRange, CaptureDefault, CaptureDefaultLoc, + Captures, ExplicitParams, ExplicitResultType, CaptureInits, + ClosingBrace, ContainsUnexpandedParameterPack); } LambdaExpr *LambdaExpr::CreateDeserialized(const ASTContext &C, - unsigned NumCaptures, - unsigned NumArrayIndexVars) { - unsigned Size = totalSizeToAlloc<Stmt *, unsigned, VarDecl *>( - NumCaptures + 1, NumArrayIndexVars ? NumCaptures + 1 : 0, - NumArrayIndexVars); + unsigned NumCaptures) { + unsigned Size = totalSizeToAlloc<Stmt *>(NumCaptures + 1); void *Mem = C.Allocate(Size); - return new (Mem) LambdaExpr(EmptyShell(), NumCaptures, NumArrayIndexVars > 0); + return new (Mem) LambdaExpr(EmptyShell(), NumCaptures); } bool LambdaExpr::isInitCapture(const LambdaCapture *C) const { @@ -979,19 +975,6 @@ LambdaExpr::capture_range LambdaExpr::implicit_captures() const { return capture_range(implicit_capture_begin(), implicit_capture_end()); } -ArrayRef<VarDecl *> -LambdaExpr::getCaptureInitIndexVars(const_capture_init_iterator Iter) const { - assert(HasArrayIndexVars && "No array index-var data?"); - - unsigned Index = Iter - capture_init_begin(); - assert(Index < getLambdaClass()->getLambdaData().NumCaptures && - "Capture index out-of-range"); - VarDecl *const *IndexVars = getArrayIndexVars(); - const unsigned *IndexStarts = getArrayIndexStarts(); - return llvm::makeArrayRef(IndexVars + IndexStarts[Index], - IndexVars + IndexStarts[Index + 1]); -} - CXXRecordDecl *LambdaExpr::getLambdaClass() const { return getType()->getAsCXXRecordDecl(); } @@ -1041,7 +1024,7 @@ ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, Expr *subexpr, bool CleanupsHaveSideEffects, ArrayRef<CleanupObject> objects) { void *buffer = C.Allocate(totalSizeToAlloc<CleanupObject>(objects.size()), - llvm::alignOf<ExprWithCleanups>()); + alignof(ExprWithCleanups)); return new (buffer) ExprWithCleanups(subexpr, CleanupsHaveSideEffects, objects); } @@ -1055,7 +1038,7 @@ ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, EmptyShell empty, unsigned numObjects) { void *buffer = C.Allocate(totalSizeToAlloc<CleanupObject>(numObjects), - llvm::alignOf<ExprWithCleanups>()); + alignof(ExprWithCleanups)); return new (buffer) ExprWithCleanups(empty, numObjects); } @@ -1154,7 +1137,7 @@ CXXDependentScopeMemberExpr::Create(const ASTContext &C, totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( HasTemplateKWAndArgsInfo, NumTemplateArgs); - void *Mem = C.Allocate(Size, llvm::alignOf<CXXDependentScopeMemberExpr>()); + void *Mem = C.Allocate(Size, alignof(CXXDependentScopeMemberExpr)); return new (Mem) CXXDependentScopeMemberExpr(C, Base, BaseType, IsArrow, OperatorLoc, QualifierLoc, @@ -1171,7 +1154,7 @@ CXXDependentScopeMemberExpr::CreateEmpty(const ASTContext &C, std::size_t Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( HasTemplateKWAndArgsInfo, NumTemplateArgs); - void *Mem = C.Allocate(Size, llvm::alignOf<CXXDependentScopeMemberExpr>()); + void *Mem = C.Allocate(Size, alignof(CXXDependentScopeMemberExpr)); CXXDependentScopeMemberExpr *E = new (Mem) CXXDependentScopeMemberExpr(C, nullptr, QualType(), 0, SourceLocation(), @@ -1255,7 +1238,7 @@ UnresolvedMemberExpr *UnresolvedMemberExpr::Create( totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( HasTemplateKWAndArgsInfo, TemplateArgs ? TemplateArgs->size() : 0); - void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedMemberExpr>()); + void *Mem = C.Allocate(Size, alignof(UnresolvedMemberExpr)); return new (Mem) UnresolvedMemberExpr( C, HasUnresolvedUsing, Base, BaseType, IsArrow, OperatorLoc, QualifierLoc, TemplateKWLoc, MemberNameInfo, TemplateArgs, Begin, End); @@ -1270,7 +1253,7 @@ UnresolvedMemberExpr::CreateEmpty(const ASTContext &C, totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( HasTemplateKWAndArgsInfo, NumTemplateArgs); - void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedMemberExpr>()); + void *Mem = C.Allocate(Size, alignof(UnresolvedMemberExpr)); UnresolvedMemberExpr *E = new (Mem) UnresolvedMemberExpr(EmptyShell()); E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo; return E; diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index 89cc9bc18ef07..adb74b80b1988 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -141,10 +141,9 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { return Cl::CL_LValue; // C99 6.5.2.5p5 says that compound literals are lvalues. - // In C++, they're prvalue temporaries. + // In C++, they're prvalue temporaries, except for file-scope arrays. case Expr::CompoundLiteralExprClass: - return Ctx.getLangOpts().CPlusPlus ? ClassifyTemporary(E->getType()) - : Cl::CL_LValue; + return !E->isLValue() ? ClassifyTemporary(E->getType()) : Cl::CL_LValue; // Expressions that are prvalues. case Expr::CXXBoolLiteralExprClass: @@ -186,6 +185,8 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::ObjCIndirectCopyRestoreExprClass: case Expr::AtomicExprClass: case Expr::CXXFoldExprClass: + case Expr::ArrayInitLoopExprClass: + case Expr::ArrayInitIndexExprClass: case Expr::NoInitExprClass: case Expr::DesignatedInitUpdateExprClass: case Expr::CoyieldExprClass: @@ -196,11 +197,20 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { return ClassifyInternal(Ctx, cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement()); - // C++ [expr.sub]p1: The result is an lvalue of type "T". - // However, subscripting vector types is more like member access. + // C, C++98 [expr.sub]p1: The result is an lvalue of type "T". + // C++11 (DR1213): in the case of an array operand, the result is an lvalue + // if that operand is an lvalue and an xvalue otherwise. + // Subscripting vector types is more like member access. case Expr::ArraySubscriptExprClass: if (cast<ArraySubscriptExpr>(E)->getBase()->getType()->isVectorType()) return ClassifyInternal(Ctx, cast<ArraySubscriptExpr>(E)->getBase()); + if (Lang.CPlusPlus11) { + // Step over the array-to-pointer decay if present, but not over the + // temporary materialization. + auto *Base = cast<ArraySubscriptExpr>(E)->getBase()->IgnoreImpCasts(); + if (Base->getType()->isArrayType()) + return ClassifyInternal(Ctx, Base); + } return Cl::CL_LValue; // C++ [expr.prim.general]p3: The result is an lvalue if the entity is a @@ -429,6 +439,7 @@ static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) { else islvalue = isa<VarDecl>(D) || isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || + isa<BindingDecl>(D) || (Ctx.getLangOpts().CPlusPlus && (isa<FunctionDecl>(D) || isa<MSPropertyDecl>(D) || isa<FunctionTemplateDecl>(D))); diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index df944e8f25f29..b3f8925b64643 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -36,6 +36,7 @@ #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/CharUnits.h" #include "clang/AST/Expr.h" #include "clang/AST/RecordLayout.h" @@ -43,7 +44,6 @@ #include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" #include <cstring> #include <functional> @@ -76,8 +76,8 @@ namespace { const Expr *Inner = Temp->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); // Keep any cv-qualifiers from the reference if we generated a temporary - // for it. - if (Inner != Temp) + // for it directly. Otherwise use the type after adjustment. + if (!Adjustments.empty()) return Inner->getType(); } @@ -109,19 +109,57 @@ namespace { return getAsBaseOrMember(E).getInt(); } + /// Given a CallExpr, try to get the alloc_size attribute. May return null. + static const AllocSizeAttr *getAllocSizeAttr(const CallExpr *CE) { + const FunctionDecl *Callee = CE->getDirectCallee(); + return Callee ? Callee->getAttr<AllocSizeAttr>() : nullptr; + } + + /// Attempts to unwrap a CallExpr (with an alloc_size attribute) from an Expr. + /// This will look through a single cast. + /// + /// Returns null if we couldn't unwrap a function with alloc_size. + static const CallExpr *tryUnwrapAllocSizeCall(const Expr *E) { + if (!E->getType()->isPointerType()) + return nullptr; + + E = E->IgnoreParens(); + // If we're doing a variable assignment from e.g. malloc(N), there will + // probably be a cast of some kind. Ignore it. + if (const auto *Cast = dyn_cast<CastExpr>(E)) + E = Cast->getSubExpr()->IgnoreParens(); + + if (const auto *CE = dyn_cast<CallExpr>(E)) + return getAllocSizeAttr(CE) ? CE : nullptr; + return nullptr; + } + + /// Determines whether or not the given Base contains a call to a function + /// with the alloc_size attribute. + static bool isBaseAnAllocSizeCall(APValue::LValueBase Base) { + const auto *E = Base.dyn_cast<const Expr *>(); + return E && E->getType()->isPointerType() && tryUnwrapAllocSizeCall(E); + } + + /// Determines if an LValue with the given LValueBase will have an unsized + /// array in its designator. /// Find the path length and type of the most-derived subobject in the given /// path, and find the size of the containing array, if any. - static - unsigned findMostDerivedSubobject(ASTContext &Ctx, QualType Base, - ArrayRef<APValue::LValuePathEntry> Path, - uint64_t &ArraySize, QualType &Type, - bool &IsArray) { + static unsigned + findMostDerivedSubobject(ASTContext &Ctx, APValue::LValueBase Base, + ArrayRef<APValue::LValuePathEntry> Path, + uint64_t &ArraySize, QualType &Type, bool &IsArray) { + // This only accepts LValueBases from APValues, and APValues don't support + // arrays that lack size info. + assert(!isBaseAnAllocSizeCall(Base) && + "Unsized arrays shouldn't appear here"); unsigned MostDerivedLength = 0; - Type = Base; + Type = getType(Base); + for (unsigned I = 0, N = Path.size(); I != N; ++I) { if (Type->isArrayType()) { const ConstantArrayType *CAT = - cast<ConstantArrayType>(Ctx.getAsArrayType(Type)); + cast<ConstantArrayType>(Ctx.getAsArrayType(Type)); Type = CAT->getElementType(); ArraySize = CAT->getSize().getZExtValue(); MostDerivedLength = I + 1; @@ -162,17 +200,23 @@ namespace { /// Is this a pointer one past the end of an object? unsigned IsOnePastTheEnd : 1; + /// Indicator of whether the first entry is an unsized array. + unsigned FirstEntryIsAnUnsizedArray : 1; + /// Indicator of whether the most-derived object is an array element. unsigned MostDerivedIsArrayElement : 1; /// The length of the path to the most-derived object of which this is a /// subobject. - unsigned MostDerivedPathLength : 29; + unsigned MostDerivedPathLength : 28; /// The size of the array of which the most-derived object is an element. /// This will always be 0 if the most-derived object is not an array /// element. 0 is not an indicator of whether or not the most-derived object /// is an array, however, because 0-length arrays are allowed. + /// + /// If the current array is an unsized array, the value of this is + /// undefined. uint64_t MostDerivedArraySize; /// The type of the most derived object referred to by this address. @@ -187,23 +231,24 @@ namespace { explicit SubobjectDesignator(QualType T) : Invalid(false), IsOnePastTheEnd(false), - MostDerivedIsArrayElement(false), MostDerivedPathLength(0), - MostDerivedArraySize(0), MostDerivedType(T) {} + FirstEntryIsAnUnsizedArray(false), MostDerivedIsArrayElement(false), + MostDerivedPathLength(0), MostDerivedArraySize(0), + MostDerivedType(T) {} SubobjectDesignator(ASTContext &Ctx, const APValue &V) : Invalid(!V.isLValue() || !V.hasLValuePath()), IsOnePastTheEnd(false), - MostDerivedIsArrayElement(false), MostDerivedPathLength(0), - MostDerivedArraySize(0) { + FirstEntryIsAnUnsizedArray(false), MostDerivedIsArrayElement(false), + MostDerivedPathLength(0), MostDerivedArraySize(0) { + assert(V.isLValue() && "Non-LValue used to make an LValue designator?"); if (!Invalid) { IsOnePastTheEnd = V.isLValueOnePastTheEnd(); ArrayRef<PathEntry> VEntries = V.getLValuePath(); Entries.insert(Entries.end(), VEntries.begin(), VEntries.end()); if (V.getLValueBase()) { bool IsArray = false; - MostDerivedPathLength = - findMostDerivedSubobject(Ctx, getType(V.getLValueBase()), - V.getLValuePath(), MostDerivedArraySize, - MostDerivedType, IsArray); + MostDerivedPathLength = findMostDerivedSubobject( + Ctx, V.getLValueBase(), V.getLValuePath(), MostDerivedArraySize, + MostDerivedType, IsArray); MostDerivedIsArrayElement = IsArray; } } @@ -214,12 +259,26 @@ namespace { Entries.clear(); } + /// Determine whether the most derived subobject is an array without a + /// known bound. + bool isMostDerivedAnUnsizedArray() const { + assert(!Invalid && "Calling this makes no sense on invalid designators"); + return Entries.size() == 1 && FirstEntryIsAnUnsizedArray; + } + + /// Determine what the most derived array's size is. Results in an assertion + /// failure if the most derived array lacks a size. + uint64_t getMostDerivedArraySize() const { + assert(!isMostDerivedAnUnsizedArray() && "Unsized array has no size"); + return MostDerivedArraySize; + } + /// Determine whether this is a one-past-the-end pointer. bool isOnePastTheEnd() const { assert(!Invalid); if (IsOnePastTheEnd) return true; - if (MostDerivedIsArrayElement && + if (!isMostDerivedAnUnsizedArray() && MostDerivedIsArrayElement && Entries[MostDerivedPathLength - 1].ArrayIndex == MostDerivedArraySize) return true; return false; @@ -247,6 +306,21 @@ namespace { MostDerivedArraySize = CAT->getSize().getZExtValue(); MostDerivedPathLength = Entries.size(); } + /// Update this designator to refer to the first element within the array of + /// elements of type T. This is an array of unknown size. + void addUnsizedArrayUnchecked(QualType ElemTy) { + PathEntry Entry; + Entry.ArrayIndex = 0; + Entries.push_back(Entry); + + MostDerivedType = ElemTy; + MostDerivedIsArrayElement = true; + // The value in MostDerivedArraySize is undefined in this case. So, set it + // to an arbitrary value that's likely to loudly break things if it's + // used. + MostDerivedArraySize = std::numeric_limits<uint64_t>::max() / 2; + MostDerivedPathLength = Entries.size(); + } /// Update this designator to refer to the given base or member of this /// object. void addDeclUnchecked(const Decl *D, bool Virtual = false) { @@ -280,10 +354,16 @@ namespace { /// Add N to the address of this subobject. void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) { if (Invalid) return; + if (isMostDerivedAnUnsizedArray()) { + // Can't verify -- trust that the user is doing the right thing (or if + // not, trust that the caller will catch the bad behavior). + Entries.back().ArrayIndex += N; + return; + } if (MostDerivedPathLength == Entries.size() && MostDerivedIsArrayElement) { Entries.back().ArrayIndex += N; - if (Entries.back().ArrayIndex > MostDerivedArraySize) { + if (Entries.back().ArrayIndex > getMostDerivedArraySize()) { diagnosePointerArithmetic(Info, E, Entries.back().ArrayIndex); setInvalid(); } @@ -310,15 +390,9 @@ namespace { /// Parent - The caller of this stack frame. CallStackFrame *Caller; - /// CallLoc - The location of the call expression for this call. - SourceLocation CallLoc; - /// Callee - The function which was called. const FunctionDecl *Callee; - /// Index - The call index of this call. - unsigned Index; - /// This - The binding for the this pointer in this call, if any. const LValue *This; @@ -333,6 +407,12 @@ namespace { /// Temporaries - Temporary lvalues materialized within this stack frame. MapTy Temporaries; + /// CallLoc - The location of the call expression for this call. + SourceLocation CallLoc; + + /// Index - The call index of this call. + unsigned Index; + CallStackFrame(EvalInfo &Info, SourceLocation CallLoc, const FunctionDecl *Callee, const LValue *This, APValue *Arguments); @@ -433,7 +513,7 @@ namespace { /// rules. For example, the RHS of (0 && foo()) is not evaluated. We can /// evaluate the expression regardless of what the RHS is, but C only allows /// certain things in certain situations. - struct EvalInfo { + struct LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) EvalInfo { ASTContext &Ctx; /// EvalStatus - Contains information about the evaluation. @@ -469,6 +549,10 @@ namespace { /// declaration whose initializer is being evaluated, if any. APValue *EvaluatingDeclValue; + /// The current array initialization index, if we're performing array + /// initialization. + uint64_t ArrayInitIndex = -1; + /// HasActiveDiagnostic - Was the previous diagnostic stored? If so, further /// notes attached to it will also be stored, otherwise they will not be. bool HasActiveDiagnostic; @@ -520,9 +604,15 @@ namespace { /// gets a chance to look at it. EM_PotentialConstantExpressionUnevaluated, - /// Evaluate as a constant expression. Continue evaluating if we find a - /// MemberExpr with a base that can't be evaluated. - EM_DesignatorFold, + /// Evaluate as a constant expression. Continue evaluating if either: + /// - We find a MemberExpr with a base that can't be evaluated. + /// - We find a variable initialized with a call to a function that has + /// the alloc_size attribute on it. + /// In either case, the LValue returned shall have an invalid base; in the + /// former, the base will be the invalid MemberExpr, in the latter, the + /// base will be either the alloc_size CallExpr or a CastExpr wrapping + /// said CallExpr. + EM_OffsetFold, } EvalMode; /// Are we checking whether the expression is a potential constant @@ -624,7 +714,7 @@ namespace { case EM_PotentialConstantExpression: case EM_ConstantExpressionUnevaluated: case EM_PotentialConstantExpressionUnevaluated: - case EM_DesignatorFold: + case EM_OffsetFold: HasActiveDiagnostic = false; return OptionalDiagnostic(); } @@ -716,7 +806,7 @@ namespace { case EM_ConstantExpression: case EM_ConstantExpressionUnevaluated: case EM_ConstantFold: - case EM_DesignatorFold: + case EM_OffsetFold: return false; } llvm_unreachable("Missed EvalMode case"); @@ -735,7 +825,7 @@ namespace { case EM_EvaluateForOverflow: case EM_IgnoreSideEffects: case EM_ConstantFold: - case EM_DesignatorFold: + case EM_OffsetFold: return true; case EM_PotentialConstantExpression: @@ -771,7 +861,7 @@ namespace { case EM_ConstantExpressionUnevaluated: case EM_ConstantFold: case EM_IgnoreSideEffects: - case EM_DesignatorFold: + case EM_OffsetFold: return false; } llvm_unreachable("Missed EvalMode case"); @@ -787,7 +877,7 @@ namespace { /// (Foo(), 1) // use noteSideEffect /// (Foo() || true) // use noteSideEffect /// Foo() + 1 // use noteFailure - LLVM_ATTRIBUTE_UNUSED_RESULT bool noteFailure() { + LLVM_NODISCARD bool noteFailure() { // Failure when evaluating some expression often means there is some // subexpression whose evaluation was skipped. Therefore, (because we // don't track whether we skipped an expression when unwinding after an @@ -801,8 +891,22 @@ namespace { } bool allowInvalidBaseExpr() const { - return EvalMode == EM_DesignatorFold; + return EvalMode == EM_OffsetFold; } + + class ArrayInitLoopIndex { + EvalInfo &Info; + uint64_t OuterIndex; + + public: + ArrayInitLoopIndex(EvalInfo &Info) + : Info(Info), OuterIndex(Info.ArrayInitIndex) { + Info.ArrayInitIndex = 0; + } + ~ArrayInitLoopIndex() { Info.ArrayInitIndex = OuterIndex; } + + operator uint64_t&() { return Info.ArrayInitIndex; } + }; }; /// Object used to treat all foldable expressions as constant expressions. @@ -838,11 +942,10 @@ namespace { struct FoldOffsetRAII { EvalInfo &Info; EvalInfo::EvaluationMode OldMode; - explicit FoldOffsetRAII(EvalInfo &Info, bool Subobject) + explicit FoldOffsetRAII(EvalInfo &Info) : Info(Info), OldMode(Info.EvalMode) { if (!Info.checkingPotentialConstantExpression()) - Info.EvalMode = Subobject ? EvalInfo::EM_DesignatorFold - : EvalInfo::EM_ConstantFold; + Info.EvalMode = EvalInfo::EM_OffsetFold; } ~FoldOffsetRAII() { Info.EvalMode = OldMode; } @@ -948,10 +1051,12 @@ bool SubobjectDesignator::checkSubobject(EvalInfo &Info, const Expr *E, void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info, const Expr *E, uint64_t N) { + // If we're complaining, we must be able to statically determine the size of + // the most derived array. if (MostDerivedPathLength == Entries.size() && MostDerivedIsArrayElement) Info.CCEDiag(E, diag::note_constexpr_array_index) << static_cast<int>(N) << /*array*/ 0 - << static_cast<unsigned>(MostDerivedArraySize); + << static_cast<unsigned>(getMostDerivedArraySize()); else Info.CCEDiag(E, diag::note_constexpr_array_index) << static_cast<int>(N) << /*non-array*/ 1; @@ -961,8 +1066,8 @@ void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info, CallStackFrame::CallStackFrame(EvalInfo &Info, SourceLocation CallLoc, const FunctionDecl *Callee, const LValue *This, APValue *Arguments) - : Info(Info), Caller(Info.CurrentCall), CallLoc(CallLoc), Callee(Callee), - Index(Info.NextCallIndex++), This(This), Arguments(Arguments) { + : Info(Info), Caller(Info.CurrentCall), Callee(Callee), This(This), + Arguments(Arguments), CallLoc(CallLoc), Index(Info.NextCallIndex++) { Info.CurrentCall = this; ++Info.CallStackDepth; } @@ -1032,7 +1137,7 @@ namespace { APSInt IntReal, IntImag; APFloat FloatReal, FloatImag; - ComplexValue() : FloatReal(APFloat::Bogus), FloatImag(APFloat::Bogus) {} + ComplexValue() : FloatReal(APFloat::Bogus()), FloatImag(APFloat::Bogus()) {} void makeComplexFloat() { IsInt = false; } bool isComplexFloat() const { return !IsInt; } @@ -1070,6 +1175,7 @@ namespace { unsigned InvalidBase : 1; unsigned CallIndex : 31; SubobjectDesignator Designator; + bool IsNullPtr; const APValue::LValueBase getLValueBase() const { return Base; } CharUnits &getLValueOffset() { return Offset; } @@ -1077,29 +1183,47 @@ namespace { unsigned getLValueCallIndex() const { return CallIndex; } SubobjectDesignator &getLValueDesignator() { return Designator; } const SubobjectDesignator &getLValueDesignator() const { return Designator;} + bool isNullPointer() const { return IsNullPtr;} void moveInto(APValue &V) const { if (Designator.Invalid) - V = APValue(Base, Offset, APValue::NoLValuePath(), CallIndex); - else + V = APValue(Base, Offset, APValue::NoLValuePath(), CallIndex, + IsNullPtr); + else { + assert(!InvalidBase && "APValues can't handle invalid LValue bases"); + assert(!Designator.FirstEntryIsAnUnsizedArray && + "Unsized array with a valid base?"); V = APValue(Base, Offset, Designator.Entries, - Designator.IsOnePastTheEnd, CallIndex); + Designator.IsOnePastTheEnd, CallIndex, IsNullPtr); + } } void setFrom(ASTContext &Ctx, const APValue &V) { - assert(V.isLValue()); + assert(V.isLValue() && "Setting LValue from a non-LValue?"); Base = V.getLValueBase(); Offset = V.getLValueOffset(); InvalidBase = false; CallIndex = V.getLValueCallIndex(); Designator = SubobjectDesignator(Ctx, V); + IsNullPtr = V.isNullPointer(); } - void set(APValue::LValueBase B, unsigned I = 0, bool BInvalid = false) { + void set(APValue::LValueBase B, unsigned I = 0, bool BInvalid = false, + bool IsNullPtr_ = false, uint64_t Offset_ = 0) { +#ifndef NDEBUG + // We only allow a few types of invalid bases. Enforce that here. + if (BInvalid) { + const auto *E = B.get<const Expr *>(); + assert((isa<MemberExpr>(E) || tryUnwrapAllocSizeCall(E)) && + "Unexpected type of invalid base"); + } +#endif + Base = B; - Offset = CharUnits::Zero(); + Offset = CharUnits::fromQuantity(Offset_); InvalidBase = BInvalid; CallIndex = I; Designator = SubobjectDesignator(getType(B)); + IsNullPtr = IsNullPtr_; } void setInvalid(APValue::LValueBase B, unsigned I = 0) { @@ -1112,7 +1236,7 @@ namespace { CheckSubobjectKind CSK) { if (Designator.Invalid) return false; - if (!Base) { + if (IsNullPtr) { Info.CCEDiag(E, diag::note_constexpr_null_subobject) << CSK; Designator.setInvalid(); @@ -1133,6 +1257,13 @@ namespace { if (checkSubobject(Info, E, isa<FieldDecl>(D) ? CSK_Field : CSK_Base)) Designator.addDeclUnchecked(D, Virtual); } + void addUnsizedArray(EvalInfo &Info, QualType ElemTy) { + assert(Designator.Entries.empty() && getType(Base)->isPointerType()); + assert(isBaseAnAllocSizeCall(Base) && + "Only alloc_size bases can have unsized arrays"); + Designator.FirstEntryIsAnUnsizedArray = true; + Designator.addUnsizedArrayUnchecked(ElemTy); + } void addArray(EvalInfo &Info, const Expr *E, const ConstantArrayType *CAT) { if (checkSubobject(Info, E, CSK_ArrayToPointer)) Designator.addArrayUnchecked(CAT); @@ -1141,9 +1272,22 @@ namespace { if (checkSubobject(Info, E, Imag ? CSK_Imag : CSK_Real)) Designator.addComplexUnchecked(EltTy, Imag); } - void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) { - if (N && checkNullPointer(Info, E, CSK_ArrayIndex)) - Designator.adjustIndex(Info, E, N); + void clearIsNullPointer() { + IsNullPtr = false; + } + void adjustOffsetAndIndex(EvalInfo &Info, const Expr *E, uint64_t Index, + CharUnits ElementSize) { + // Compute the new offset in the appropriate width. + Offset += Index * ElementSize; + if (Index && checkNullPointer(Info, E, CSK_ArrayIndex)) + Designator.adjustIndex(Info, E, Index); + if (Index) + clearIsNullPointer(); + } + void adjustOffset(CharUnits N) { + Offset += N; + if (N.getQuantity()) + clearIsNullPointer(); } }; @@ -2018,7 +2162,7 @@ static bool HandleLValueMember(EvalInfo &Info, const Expr *E, LValue &LVal, } unsigned I = FD->getFieldIndex(); - LVal.Offset += Info.Ctx.toCharUnitsFromBits(RL->getFieldOffset(I)); + LVal.adjustOffset(Info.Ctx.toCharUnitsFromBits(RL->getFieldOffset(I))); LVal.addDecl(Info, E, FD); return true; } @@ -2072,9 +2216,7 @@ static bool HandleLValueArrayAdjustment(EvalInfo &Info, const Expr *E, if (!HandleSizeof(Info, E->getExprLoc(), EltTy, SizeOfPointee)) return false; - // Compute the new offset in the appropriate width. - LVal.Offset += Adjustment * SizeOfPointee; - LVal.adjustIndex(Info, E, Adjustment); + LVal.adjustOffsetAndIndex(Info, E, Adjustment, SizeOfPointee); return true; } @@ -2125,7 +2267,22 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, // If this is a local variable, dig out its value. if (Frame) { Result = Frame->getTemporary(VD); - assert(Result && "missing value for local variable"); + if (!Result) { + // Assume variables referenced within a lambda's call operator that were + // not declared within the call operator are captures and during checking + // of a potential constant expression, assume they are unknown constant + // expressions. + assert(isLambdaCallOperator(Frame->Callee) && + (VD->getDeclContext() != Frame->Callee || VD->isInitCapture()) && + "missing value for local variable"); + if (Info.checkingPotentialConstantExpression()) + return false; + // FIXME: implement capture evaluation during constant expr evaluation. + Info.FFDiag(E->getLocStart(), + diag::note_unimplemented_constexpr_lambda_feature_ast) + << "captures not currently allowed"; + return false; + } return true; } @@ -2771,6 +2928,9 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, } else { Info.CCEDiag(E); } + } else if (BaseType.isConstQualified() && VD->hasDefinition(Info.Ctx)) { + Info.CCEDiag(E, diag::note_constexpr_ltor_non_constexpr) << VD; + // Keep evaluating to see what we can do. } else { // FIXME: Allow folding of values of any literal type in all languages. if (Info.checkingPotentialConstantExpression() && @@ -2892,7 +3052,6 @@ static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, // In C99, a CompoundLiteralExpr is an lvalue, and we defer evaluating the // initializer until now for such expressions. Such an expression can't be // an ICE in C, so this only matters for fold. - assert(!Info.getLangOpts().CPlusPlus && "lvalue compound literal in c++?"); if (Type.isVolatileQualified()) { Info.FFDiag(Conv); return false; @@ -3385,38 +3544,51 @@ enum EvalStmtResult { }; } -static bool EvaluateDecl(EvalInfo &Info, const Decl *D) { - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { - // We don't need to evaluate the initializer for a static local. - if (!VD->hasLocalStorage()) - return true; +static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) { + // We don't need to evaluate the initializer for a static local. + if (!VD->hasLocalStorage()) + return true; - LValue Result; - Result.set(VD, Info.CurrentCall->Index); - APValue &Val = Info.CurrentCall->createTemporary(VD, true); + LValue Result; + Result.set(VD, Info.CurrentCall->Index); + APValue &Val = Info.CurrentCall->createTemporary(VD, true); - const Expr *InitE = VD->getInit(); - if (!InitE) { - Info.FFDiag(D->getLocStart(), diag::note_constexpr_uninitialized) - << false << VD->getType(); - Val = APValue(); - return false; - } + const Expr *InitE = VD->getInit(); + if (!InitE) { + Info.FFDiag(VD->getLocStart(), diag::note_constexpr_uninitialized) + << false << VD->getType(); + Val = APValue(); + return false; + } - if (InitE->isValueDependent()) - return false; + if (InitE->isValueDependent()) + return false; - if (!EvaluateInPlace(Val, Info, Result, InitE)) { - // Wipe out any partially-computed value, to allow tracking that this - // evaluation failed. - Val = APValue(); - return false; - } + if (!EvaluateInPlace(Val, Info, Result, InitE)) { + // Wipe out any partially-computed value, to allow tracking that this + // evaluation failed. + Val = APValue(); + return false; } return true; } +static bool EvaluateDecl(EvalInfo &Info, const Decl *D) { + bool OK = true; + + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) + OK &= EvaluateVarDecl(Info, VD); + + if (const DecompositionDecl *DD = dyn_cast<DecompositionDecl>(D)) + for (auto *BD : DD->bindings()) + if (auto *VD = BD->getHoldingVar()) + OK &= EvaluateDecl(Info, VD); + + return OK; +} + + /// Evaluate a condition (either a variable declaration or an expression). static bool EvaluateCond(EvalInfo &Info, const VarDecl *CondDecl, const Expr *Cond, bool &Result) { @@ -4389,8 +4561,11 @@ public: } // Don't call function pointers which have been cast to some other type. - if (!Info.Ctx.hasSameType(CalleeType->getPointeeType(), FD->getType())) + // Per DR (no number yet), the caller and callee can differ in noexcept. + if (!Info.Ctx.hasSameFunctionTypeIgnoringExceptionSpec( + CalleeType->getPointeeType(), FD->getType())) { return Error(E); + } } else return Error(E); @@ -4683,7 +4858,7 @@ public: // * VarDecl // * FunctionDecl // - Literals -// * CompoundLiteralExpr in C +// * CompoundLiteralExpr in C (and in global scope in C++) // * StringLiteral // * CXXTypeidExpr // * PredefinedExpr @@ -4770,13 +4945,26 @@ bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { return Success(FD); if (const VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) return VisitVarDecl(E, VD); + if (const BindingDecl *BD = dyn_cast<BindingDecl>(E->getDecl())) + return Visit(BD->getBinding()); return Error(E); } + bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { CallStackFrame *Frame = nullptr; - if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1) - Frame = Info.CurrentCall; + if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1) { + // Only if a local variable was declared in the function currently being + // evaluated, do we expect to be able to find its value in the current + // frame. (Otherwise it was likely declared in an enclosing context and + // could either have a valid evaluatable value (for e.g. a constexpr + // variable) or be ill-formed (and trigger an appropriate evaluation + // diagnostic)). + if (Info.CurrentCall->Callee && + Info.CurrentCall->Callee->Equals(VD->getDeclContext())) { + Frame = Info.CurrentCall; + } + } if (!VD->getType()->isReferenceType()) { if (Frame) { @@ -4865,7 +5053,8 @@ bool LValueExprEvaluator::VisitMaterializeTemporaryExpr( bool LValueExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { - assert(!Info.getLangOpts().CPlusPlus && "lvalue compound literal in c++?"); + assert((!Info.getLangOpts().CPlusPlus || E->isFileScope()) && + "lvalue compound literal in c++?"); // Defer visiting the literal until the lvalue-to-rvalue conversion. We can // only see this when folding in C, so there's no standard to follow here. return Success(E); @@ -5000,6 +5189,105 @@ bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) { // Pointer Evaluation //===----------------------------------------------------------------------===// +/// \brief Attempts to compute the number of bytes available at the pointer +/// returned by a function with the alloc_size attribute. Returns true if we +/// were successful. Places an unsigned number into `Result`. +/// +/// This expects the given CallExpr to be a call to a function with an +/// alloc_size attribute. +static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx, + const CallExpr *Call, + llvm::APInt &Result) { + const AllocSizeAttr *AllocSize = getAllocSizeAttr(Call); + + // alloc_size args are 1-indexed, 0 means not present. + assert(AllocSize && AllocSize->getElemSizeParam() != 0); + unsigned SizeArgNo = AllocSize->getElemSizeParam() - 1; + unsigned BitsInSizeT = Ctx.getTypeSize(Ctx.getSizeType()); + if (Call->getNumArgs() <= SizeArgNo) + return false; + + auto EvaluateAsSizeT = [&](const Expr *E, APSInt &Into) { + if (!E->EvaluateAsInt(Into, Ctx, Expr::SE_AllowSideEffects)) + return false; + if (Into.isNegative() || !Into.isIntN(BitsInSizeT)) + return false; + Into = Into.zextOrSelf(BitsInSizeT); + return true; + }; + + APSInt SizeOfElem; + if (!EvaluateAsSizeT(Call->getArg(SizeArgNo), SizeOfElem)) + return false; + + if (!AllocSize->getNumElemsParam()) { + Result = std::move(SizeOfElem); + return true; + } + + APSInt NumberOfElems; + // Argument numbers start at 1 + unsigned NumArgNo = AllocSize->getNumElemsParam() - 1; + if (!EvaluateAsSizeT(Call->getArg(NumArgNo), NumberOfElems)) + return false; + + bool Overflow; + llvm::APInt BytesAvailable = SizeOfElem.umul_ov(NumberOfElems, Overflow); + if (Overflow) + return false; + + Result = std::move(BytesAvailable); + return true; +} + +/// \brief Convenience function. LVal's base must be a call to an alloc_size +/// function. +static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx, + const LValue &LVal, + llvm::APInt &Result) { + assert(isBaseAnAllocSizeCall(LVal.getLValueBase()) && + "Can't get the size of a non alloc_size function"); + const auto *Base = LVal.getLValueBase().get<const Expr *>(); + const CallExpr *CE = tryUnwrapAllocSizeCall(Base); + return getBytesReturnedByAllocSizeCall(Ctx, CE, Result); +} + +/// \brief Attempts to evaluate the given LValueBase as the result of a call to +/// a function with the alloc_size attribute. If it was possible to do so, this +/// function will return true, make Result's Base point to said function call, +/// and mark Result's Base as invalid. +static bool evaluateLValueAsAllocSize(EvalInfo &Info, APValue::LValueBase Base, + LValue &Result) { + if (!Info.allowInvalidBaseExpr() || Base.isNull()) + return false; + + // Because we do no form of static analysis, we only support const variables. + // + // Additionally, we can't support parameters, nor can we support static + // variables (in the latter case, use-before-assign isn't UB; in the former, + // we have no clue what they'll be assigned to). + const auto *VD = + dyn_cast_or_null<VarDecl>(Base.dyn_cast<const ValueDecl *>()); + if (!VD || !VD->isLocalVarDecl() || !VD->getType().isConstQualified()) + return false; + + const Expr *Init = VD->getAnyInitializer(); + if (!Init) + return false; + + const Expr *E = Init->IgnoreParens(); + if (!tryUnwrapAllocSizeCall(E)) + return false; + + // Store E instead of E unwrapped so that the type of the LValue's base is + // what the user wanted. + Result.setInvalid(E); + + QualType Pointee = E->getType()->castAs<PointerType>()->getPointeeType(); + Result.addUnsizedArray(Info, Pointee); + return true; +} + namespace { class PointerExprEvaluator : public ExprEvaluatorBase<PointerExprEvaluator> { @@ -5009,6 +5297,8 @@ class PointerExprEvaluator Result.set(E); return true; } + + bool visitNonBuiltinCallExpr(const CallExpr *E); public: PointerExprEvaluator(EvalInfo &info, LValue &Result) @@ -5019,7 +5309,9 @@ public: return true; } bool ZeroInitialization(const Expr *E) { - return Success((Expr*)nullptr); + auto Offset = Info.Ctx.getTargetNullPointerValue(E->getType()); + Result.set((Expr*)nullptr, 0, false, true, Offset); + return true; } bool VisitBinaryOperator(const BinaryOperator *E); @@ -5032,6 +5324,7 @@ public: bool VisitAddrLabelExpr(const AddrLabelExpr *E) { return Success(E); } bool VisitCallExpr(const CallExpr *E); + bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp); bool VisitBlockExpr(const BlockExpr *E) { if (!E->getBlockDecl()->hasCaptures()) return Success(E); @@ -5117,6 +5410,8 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { else CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; } + if (E->getCastKind() == CK_AddressSpaceConversion && Result.IsNullPtr) + ZeroInitialization(E); return true; case CK_DerivedToBase: @@ -5158,6 +5453,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { Result.Offset = CharUnits::fromQuantity(N); Result.CallIndex = 0; Result.Designator.setInvalid(); + Result.IsNullPtr = false; return true; } else { // Cast is of an lvalue, no need to change value. @@ -5185,6 +5481,19 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { case CK_FunctionToPointerDecay: return EvaluateLValue(SubExpr, Result, Info); + + case CK_LValueToRValue: { + LValue LVal; + if (!EvaluateLValue(E->getSubExpr(), LVal, Info)) + return false; + + APValue RVal; + // Note, we use the subexpression's type in order to retain cv-qualifiers. + if (!handleLValueToRValueConversion(Info, E, E->getSubExpr()->getType(), + LVal, RVal)) + return evaluateLValueAsAllocSize(Info, LVal.Base, Result); + return Success(RVal, E); + } } return ExprEvaluatorBaseTy::VisitCastExpr(E); @@ -5222,11 +5531,33 @@ static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E) { return GetAlignOfType(Info, E->getType()); } +// To be clear: this happily visits unsupported builtins. Better name welcomed. +bool PointerExprEvaluator::visitNonBuiltinCallExpr(const CallExpr *E) { + if (ExprEvaluatorBaseTy::VisitCallExpr(E)) + return true; + + if (!(Info.allowInvalidBaseExpr() && getAllocSizeAttr(E))) + return false; + + Result.setInvalid(E); + QualType PointeeTy = E->getType()->castAs<PointerType>()->getPointeeType(); + Result.addUnsizedArray(Info, PointeeTy); + return true; +} + bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) { if (IsStringLiteralCall(E)) return Success(E); - switch (E->getBuiltinCallee()) { + if (unsigned BuiltinOp = E->getBuiltinCallee()) + return VisitBuiltinCallExpr(E, BuiltinOp); + + return visitNonBuiltinCallExpr(E); +} + +bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, + unsigned BuiltinOp) { + switch (BuiltinOp) { case Builtin::BI__builtin_addressof: return EvaluateLValue(E->getArg(0), Result, Info); case Builtin::BI__builtin_assume_aligned: { @@ -5264,8 +5595,8 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) { if (BaseAlignment < Align) { Result.Designator.setInvalid(); - // FIXME: Quantities here cast to integers because the plural modifier - // does not work on APSInts yet. + // FIXME: Quantities here cast to integers because the plural modifier + // does not work on APSInts yet. CCEDiag(E->getArg(0), diag::note_constexpr_baa_insufficient_alignment) << 0 << (int) BaseAlignment.getQuantity() @@ -5294,8 +5625,93 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) { return true; } + + case Builtin::BIstrchr: + case Builtin::BIwcschr: + case Builtin::BImemchr: + case Builtin::BIwmemchr: + if (Info.getLangOpts().CPlusPlus11) + Info.CCEDiag(E, diag::note_constexpr_invalid_function) + << /*isConstexpr*/0 << /*isConstructor*/0 + << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'"); + else + Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); + // Fall through. + case Builtin::BI__builtin_strchr: + case Builtin::BI__builtin_wcschr: + case Builtin::BI__builtin_memchr: + case Builtin::BI__builtin_wmemchr: { + if (!Visit(E->getArg(0))) + return false; + APSInt Desired; + if (!EvaluateInteger(E->getArg(1), Desired, Info)) + return false; + uint64_t MaxLength = uint64_t(-1); + if (BuiltinOp != Builtin::BIstrchr && + BuiltinOp != Builtin::BIwcschr && + BuiltinOp != Builtin::BI__builtin_strchr && + BuiltinOp != Builtin::BI__builtin_wcschr) { + APSInt N; + if (!EvaluateInteger(E->getArg(2), N, Info)) + return false; + MaxLength = N.getExtValue(); + } + + QualType CharTy = E->getArg(0)->getType()->getPointeeType(); + + // Figure out what value we're actually looking for (after converting to + // the corresponding unsigned type if necessary). + uint64_t DesiredVal; + bool StopAtNull = false; + switch (BuiltinOp) { + case Builtin::BIstrchr: + case Builtin::BI__builtin_strchr: + // strchr compares directly to the passed integer, and therefore + // always fails if given an int that is not a char. + if (!APSInt::isSameValue(HandleIntToIntCast(Info, E, CharTy, + E->getArg(1)->getType(), + Desired), + Desired)) + return ZeroInitialization(E); + StopAtNull = true; + // Fall through. + case Builtin::BImemchr: + case Builtin::BI__builtin_memchr: + // memchr compares by converting both sides to unsigned char. That's also + // correct for strchr if we get this far (to cope with plain char being + // unsigned in the strchr case). + DesiredVal = Desired.trunc(Info.Ctx.getCharWidth()).getZExtValue(); + break; + + case Builtin::BIwcschr: + case Builtin::BI__builtin_wcschr: + StopAtNull = true; + // Fall through. + case Builtin::BIwmemchr: + case Builtin::BI__builtin_wmemchr: + // wcschr and wmemchr are given a wchar_t to look for. Just use it. + DesiredVal = Desired.getZExtValue(); + break; + } + + for (; MaxLength; --MaxLength) { + APValue Char; + if (!handleLValueToRValueConversion(Info, E, CharTy, Result, Char) || + !Char.isInt()) + return false; + if (Char.getInt().getZExtValue() == DesiredVal) + return true; + if (StopAtNull && !Char.getInt()) + break; + if (!HandleLValueArrayAdjustment(Info, E, Result, CharTy, 1)) + return false; + } + // Not found: return nullptr. + return ZeroInitialization(E); + } + default: - return ExprEvaluatorBaseTy::VisitCallExpr(E); + return visitNonBuiltinCallExpr(E); } } @@ -5535,6 +5951,9 @@ bool RecordExprEvaluator::VisitCastExpr(const CastExpr *E) { } bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { + if (E->isTransparent()) + return Visit(E->getInit(0)); + const RecordDecl *RD = E->getType()->castAs<RecordType>()->getDecl(); if (RD->isInvalidDecl()) return false; const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); @@ -5890,7 +6309,7 @@ bool VectorExprEvaluator::VisitCastExpr(const CastExpr *E) { if (EltTy->isRealFloatingType()) { const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(EltTy); unsigned FloatEltSize = EltSize; - if (&Sem == &APFloat::x87DoubleExtended) + if (&Sem == &APFloat::x87DoubleExtended()) FloatEltSize = 80; for (unsigned i = 0; i < NElts; i++) { llvm::APInt Elt; @@ -6030,6 +6449,7 @@ namespace { return handleCallExpr(E, Result, &This); } bool VisitInitListExpr(const InitListExpr *E); + bool VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E); bool VisitCXXConstructExpr(const CXXConstructExpr *E); bool VisitCXXConstructExpr(const CXXConstructExpr *E, const LValue &Subobject, @@ -6112,6 +6532,35 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) { FillerExpr) && Success; } +bool ArrayExprEvaluator::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) { + if (E->getCommonExpr() && + !Evaluate(Info.CurrentCall->createTemporary(E->getCommonExpr(), false), + Info, E->getCommonExpr()->getSourceExpr())) + return false; + + auto *CAT = cast<ConstantArrayType>(E->getType()->castAsArrayTypeUnsafe()); + + uint64_t Elements = CAT->getSize().getZExtValue(); + Result = APValue(APValue::UninitArray(), Elements, Elements); + + LValue Subobject = This; + Subobject.addArray(Info, E, CAT); + + bool Success = true; + for (EvalInfo::ArrayInitLoopIndex Index(Info); Index != Elements; ++Index) { + if (!EvaluateInPlace(Result.getArrayInitializedElt(Index), + Info, Subobject, E->getSubExpr()) || + !HandleLValueArrayAdjustment(Info, E, Subobject, + CAT->getElementType(), 1)) { + if (!Info.noteFailure()) + return false; + Success = false; + } + } + + return Success; +} + bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { return VisitCXXConstructExpr(E, This, &Result, E->getType()); } @@ -6252,6 +6701,7 @@ public: } bool VisitCallExpr(const CallExpr *E); + bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp); bool VisitBinaryOperator(const BinaryOperator *E); bool VisitOffsetOfExpr(const OffsetOfExpr *E); bool VisitUnaryOperator(const UnaryOperator *E); @@ -6266,6 +6716,16 @@ public: bool VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E) { return Success(E->getValue(), E); } + + bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E) { + if (Info.ArrayInitIndex == uint64_t(-1)) { + // We were asked to evaluate this subexpression independent of the + // enclosing ArrayInitLoopExpr. We can't do that. + Info.FFDiag(E); + return false; + } + return Success(Info.ArrayInitIndex, E); + } // Note, GNU defines __null as an integer, not a pointer. bool VisitGNUNullExpr(const GNUNullExpr *E) { @@ -6290,8 +6750,6 @@ public: bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E); bool VisitSizeOfPackExpr(const SizeOfPackExpr *E); -private: - bool TryEvaluateBuiltinObjectSize(const CallExpr *E, unsigned Type); // FIXME: Missing: array subscript of vector, member of vector }; } // end anonymous namespace @@ -6563,7 +7021,7 @@ static QualType getObjectType(APValue::LValueBase B) { } /// A more selective version of E->IgnoreParenCasts for -/// TryEvaluateBuiltinObjectSize. This ignores some casts/parens that serve only +/// tryEvaluateBuiltinObjectSize. This ignores some casts/parens that serve only /// to change the type of E. /// Ex. For E = `(short*)((char*)(&foo))`, returns `&foo` /// @@ -6630,82 +7088,191 @@ static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) { } } + unsigned I = 0; QualType BaseType = getType(Base); - for (int I = 0, E = LVal.Designator.Entries.size(); I != E; ++I) { + if (LVal.Designator.FirstEntryIsAnUnsizedArray) { + assert(isBaseAnAllocSizeCall(Base) && + "Unsized array in non-alloc_size call?"); + // If this is an alloc_size base, we should ignore the initial array index + ++I; + BaseType = BaseType->castAs<PointerType>()->getPointeeType(); + } + + for (unsigned E = LVal.Designator.Entries.size(); I != E; ++I) { + const auto &Entry = LVal.Designator.Entries[I]; if (BaseType->isArrayType()) { // Because __builtin_object_size treats arrays as objects, we can ignore // the index iff this is the last array in the Designator. if (I + 1 == E) return true; - auto *CAT = cast<ConstantArrayType>(Ctx.getAsArrayType(BaseType)); - uint64_t Index = LVal.Designator.Entries[I].ArrayIndex; + const auto *CAT = cast<ConstantArrayType>(Ctx.getAsArrayType(BaseType)); + uint64_t Index = Entry.ArrayIndex; if (Index + 1 != CAT->getSize()) return false; BaseType = CAT->getElementType(); } else if (BaseType->isAnyComplexType()) { - auto *CT = BaseType->castAs<ComplexType>(); - uint64_t Index = LVal.Designator.Entries[I].ArrayIndex; + const auto *CT = BaseType->castAs<ComplexType>(); + uint64_t Index = Entry.ArrayIndex; if (Index != 1) return false; BaseType = CT->getElementType(); - } else if (auto *FD = getAsField(LVal.Designator.Entries[I])) { + } else if (auto *FD = getAsField(Entry)) { bool Invalid; if (!IsLastOrInvalidFieldDecl(FD, Invalid)) return Invalid; BaseType = FD->getType(); } else { - assert(getAsBaseClass(LVal.Designator.Entries[I]) != nullptr && - "Expecting cast to a base class"); + assert(getAsBaseClass(Entry) && "Expecting cast to a base class"); return false; } } return true; } -/// Tests to see if the LValue has a designator (that isn't necessarily valid). +/// Tests to see if the LValue has a user-specified designator (that isn't +/// necessarily valid). Note that this always returns 'true' if the LValue has +/// an unsized array as its first designator entry, because there's currently no +/// way to tell if the user typed *foo or foo[0]. static bool refersToCompleteObject(const LValue &LVal) { - if (LVal.Designator.Invalid || !LVal.Designator.Entries.empty()) + if (LVal.Designator.Invalid) return false; + if (!LVal.Designator.Entries.empty()) + return LVal.Designator.isMostDerivedAnUnsizedArray(); + if (!LVal.InvalidBase) return true; - auto *E = LVal.Base.dyn_cast<const Expr *>(); - (void)E; - assert(E != nullptr && isa<MemberExpr>(E)); - return false; + // If `E` is a MemberExpr, then the first part of the designator is hiding in + // the LValueBase. + const auto *E = LVal.Base.dyn_cast<const Expr *>(); + return !E || !isa<MemberExpr>(E); +} + +/// Attempts to detect a user writing into a piece of memory that's impossible +/// to figure out the size of by just using types. +static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const LValue &LVal) { + const SubobjectDesignator &Designator = LVal.Designator; + // Notes: + // - Users can only write off of the end when we have an invalid base. Invalid + // bases imply we don't know where the memory came from. + // - We used to be a bit more aggressive here; we'd only be conservative if + // the array at the end was flexible, or if it had 0 or 1 elements. This + // broke some common standard library extensions (PR30346), but was + // otherwise seemingly fine. It may be useful to reintroduce this behavior + // with some sort of whitelist. OTOH, it seems that GCC is always + // conservative with the last element in structs (if it's an array), so our + // current behavior is more compatible than a whitelisting approach would + // be. + return LVal.InvalidBase && + Designator.Entries.size() == Designator.MostDerivedPathLength && + Designator.MostDerivedIsArrayElement && + isDesignatorAtObjectEnd(Ctx, LVal); +} + +/// Converts the given APInt to CharUnits, assuming the APInt is unsigned. +/// Fails if the conversion would cause loss of precision. +static bool convertUnsignedAPIntToCharUnits(const llvm::APInt &Int, + CharUnits &Result) { + auto CharUnitsMax = std::numeric_limits<CharUnits::QuantityType>::max(); + if (Int.ugt(CharUnitsMax)) + return false; + Result = CharUnits::fromQuantity(Int.getZExtValue()); + return true; } -/// Tries to evaluate the __builtin_object_size for @p E. If successful, returns -/// true and stores the result in @p Size. +/// Helper for tryEvaluateBuiltinObjectSize -- Given an LValue, this will +/// determine how many bytes exist from the beginning of the object to either +/// the end of the current subobject, or the end of the object itself, depending +/// on what the LValue looks like + the value of Type. /// -/// If @p WasError is non-null, this will report whether the failure to evaluate -/// is to be treated as an Error in IntExprEvaluator. -static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type, - EvalInfo &Info, uint64_t &Size, - bool *WasError = nullptr) { - if (WasError != nullptr) - *WasError = false; - - auto Error = [&](const Expr *E) { - if (WasError != nullptr) - *WasError = true; +/// If this returns false, the value of Result is undefined. +static bool determineEndOffset(EvalInfo &Info, SourceLocation ExprLoc, + unsigned Type, const LValue &LVal, + CharUnits &EndOffset) { + bool DetermineForCompleteObject = refersToCompleteObject(LVal); + + // We want to evaluate the size of the entire object. This is a valid fallback + // for when Type=1 and the designator is invalid, because we're asked for an + // upper-bound. + if (!(Type & 1) || LVal.Designator.Invalid || DetermineForCompleteObject) { + // Type=3 wants a lower bound, so we can't fall back to this. + if (Type == 3 && !DetermineForCompleteObject) + return false; + + llvm::APInt APEndOffset; + if (isBaseAnAllocSizeCall(LVal.getLValueBase()) && + getBytesReturnedByAllocSizeCall(Info.Ctx, LVal, APEndOffset)) + return convertUnsignedAPIntToCharUnits(APEndOffset, EndOffset); + + if (LVal.InvalidBase) + return false; + + QualType BaseTy = getObjectType(LVal.getLValueBase()); + return !BaseTy.isNull() && HandleSizeof(Info, ExprLoc, BaseTy, EndOffset); + } + + // We want to evaluate the size of a subobject. + const SubobjectDesignator &Designator = LVal.Designator; + + // The following is a moderately common idiom in C: + // + // struct Foo { int a; char c[1]; }; + // struct Foo *F = (struct Foo *)malloc(sizeof(struct Foo) + strlen(Bar)); + // strcpy(&F->c[0], Bar); + // + // In order to not break too much legacy code, we need to support it. + if (isUserWritingOffTheEnd(Info.Ctx, LVal)) { + // If we can resolve this to an alloc_size call, we can hand that back, + // because we know for certain how many bytes there are to write to. + llvm::APInt APEndOffset; + if (isBaseAnAllocSizeCall(LVal.getLValueBase()) && + getBytesReturnedByAllocSizeCall(Info.Ctx, LVal, APEndOffset)) + return convertUnsignedAPIntToCharUnits(APEndOffset, EndOffset); + + // If we cannot determine the size of the initial allocation, then we can't + // given an accurate upper-bound. However, we are still able to give + // conservative lower-bounds for Type=3. + if (Type == 1) + return false; + } + + CharUnits BytesPerElem; + if (!HandleSizeof(Info, ExprLoc, Designator.MostDerivedType, BytesPerElem)) return false; - }; - auto Success = [&](uint64_t S, const Expr *E) { - Size = S; - return true; - }; + // According to the GCC documentation, we want the size of the subobject + // denoted by the pointer. But that's not quite right -- what we actually + // want is the size of the immediately-enclosing array, if there is one. + int64_t ElemsRemaining; + if (Designator.MostDerivedIsArrayElement && + Designator.Entries.size() == Designator.MostDerivedPathLength) { + uint64_t ArraySize = Designator.getMostDerivedArraySize(); + uint64_t ArrayIndex = Designator.Entries.back().ArrayIndex; + ElemsRemaining = ArraySize <= ArrayIndex ? 0 : ArraySize - ArrayIndex; + } else { + ElemsRemaining = Designator.isOnePastTheEnd() ? 0 : 1; + } + EndOffset = LVal.getLValueOffset() + BytesPerElem * ElemsRemaining; + return true; +} + +/// \brief Tries to evaluate the __builtin_object_size for @p E. If successful, +/// returns true and stores the result in @p Size. +/// +/// If @p WasError is non-null, this will report whether the failure to evaluate +/// is to be treated as an Error in IntExprEvaluator. +static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type, + EvalInfo &Info, uint64_t &Size) { // Determine the denoted object. - LValue Base; + LValue LVal; { // The operand of __builtin_object_size is never evaluated for side-effects. // If there are any, but we can determine the pointed-to object anyway, then // ignore the side-effects. SpeculativeEvaluationRAII SpeculativeEval(Info); - FoldOffsetRAII Fold(Info, Type & 1); + FoldOffsetRAII Fold(Info); if (E->isGLValue()) { // It's possible for us to be given GLValues if we're called via @@ -6713,118 +7280,40 @@ static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type, APValue RVal; if (!EvaluateAsRValue(Info, E, RVal)) return false; - Base.setFrom(Info.Ctx, RVal); - } else if (!EvaluatePointer(ignorePointerCastsAndParens(E), Base, Info)) + LVal.setFrom(Info.Ctx, RVal); + } else if (!EvaluatePointer(ignorePointerCastsAndParens(E), LVal, Info)) return false; } - CharUnits BaseOffset = Base.getLValueOffset(); // If we point to before the start of the object, there are no accessible // bytes. - if (BaseOffset.isNegative()) - return Success(0, E); - - // In the case where we're not dealing with a subobject, we discard the - // subobject bit. - bool SubobjectOnly = (Type & 1) != 0 && !refersToCompleteObject(Base); - - // If Type & 1 is 0, we need to be able to statically guarantee that the bytes - // exist. If we can't verify the base, then we can't do that. - // - // As a special case, we produce a valid object size for an unknown object - // with a known designator if Type & 1 is 1. For instance: - // - // extern struct X { char buff[32]; int a, b, c; } *p; - // int a = __builtin_object_size(p->buff + 4, 3); // returns 28 - // int b = __builtin_object_size(p->buff + 4, 2); // returns 0, not 40 - // - // This matches GCC's behavior. - if (Base.InvalidBase && !SubobjectOnly) - return Error(E); - - // If we're not examining only the subobject, then we reset to a complete - // object designator - // - // If Type is 1 and we've lost track of the subobject, just find the complete - // object instead. (If Type is 3, that's not correct behavior and we should - // return 0 instead.) - LValue End = Base; - if (!SubobjectOnly || (End.Designator.Invalid && Type == 1)) { - QualType T = getObjectType(End.getLValueBase()); - if (T.isNull()) - End.Designator.setInvalid(); - else { - End.Designator = SubobjectDesignator(T); - End.Offset = CharUnits::Zero(); - } + if (LVal.getLValueOffset().isNegative()) { + Size = 0; + return true; } - // If it is not possible to determine which objects ptr points to at compile - // time, __builtin_object_size should return (size_t) -1 for type 0 or 1 - // and (size_t) 0 for type 2 or 3. - if (End.Designator.Invalid) - return false; - - // According to the GCC documentation, we want the size of the subobject - // denoted by the pointer. But that's not quite right -- what we actually - // want is the size of the immediately-enclosing array, if there is one. - int64_t AmountToAdd = 1; - if (End.Designator.MostDerivedIsArrayElement && - End.Designator.Entries.size() == End.Designator.MostDerivedPathLength) { - // We got a pointer to an array. Step to its end. - AmountToAdd = End.Designator.MostDerivedArraySize - - End.Designator.Entries.back().ArrayIndex; - } else if (End.Designator.isOnePastTheEnd()) { - // We're already pointing at the end of the object. - AmountToAdd = 0; - } - - QualType PointeeType = End.Designator.MostDerivedType; - assert(!PointeeType.isNull()); - if (PointeeType->isIncompleteType() || PointeeType->isFunctionType()) - return Error(E); - - if (!HandleLValueArrayAdjustment(Info, E, End, End.Designator.MostDerivedType, - AmountToAdd)) - return false; - - auto EndOffset = End.getLValueOffset(); - - // The following is a moderately common idiom in C: - // - // struct Foo { int a; char c[1]; }; - // struct Foo *F = (struct Foo *)malloc(sizeof(struct Foo) + strlen(Bar)); - // strcpy(&F->c[0], Bar); - // - // So, if we see that we're examining a 1-length (or 0-length) array at the - // end of a struct with an unknown base, we give up instead of breaking code - // that behaves this way. Note that we only do this when Type=1, because - // Type=3 is a lower bound, so answering conservatively is fine. - if (End.InvalidBase && SubobjectOnly && Type == 1 && - End.Designator.Entries.size() == End.Designator.MostDerivedPathLength && - End.Designator.MostDerivedIsArrayElement && - End.Designator.MostDerivedArraySize < 2 && - isDesignatorAtObjectEnd(Info.Ctx, End)) + CharUnits EndOffset; + if (!determineEndOffset(Info, E->getExprLoc(), Type, LVal, EndOffset)) return false; - if (BaseOffset > EndOffset) - return Success(0, E); - - return Success((EndOffset - BaseOffset).getQuantity(), E); + // If we've fallen outside of the end offset, just pretend there's nothing to + // write to/read from. + if (EndOffset <= LVal.getLValueOffset()) + Size = 0; + else + Size = (EndOffset - LVal.getLValueOffset()).getQuantity(); + return true; } -bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E, - unsigned Type) { - uint64_t Size; - bool WasError; - if (::tryEvaluateBuiltinObjectSize(E->getArg(0), Type, Info, Size, &WasError)) - return Success(Size, E); - if (WasError) - return Error(E); - return false; +bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { + if (unsigned BuiltinOp = E->getBuiltinCallee()) + return VisitBuiltinCallExpr(E, BuiltinOp); + + return ExprEvaluatorBaseTy::VisitCallExpr(E); } -bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { +bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, + unsigned BuiltinOp) { switch (unsigned BuiltinOp = E->getBuiltinCallee()) { default: return ExprEvaluatorBaseTy::VisitCallExpr(E); @@ -6835,8 +7324,9 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { E->getArg(1)->EvaluateKnownConstInt(Info.Ctx).getZExtValue(); assert(Type <= 3 && "unexpected type"); - if (TryEvaluateBuiltinObjectSize(E, Type)) - return true; + uint64_t Size; + if (tryEvaluateBuiltinObjectSize(E->getArg(0), Type, Info, Size)) + return Success(Size, E); if (E->getArg(0)->HasSideEffects(Info.Ctx)) return Success((Type & 2) ? 0 : -1, E); @@ -6849,7 +7339,7 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { case EvalInfo::EM_ConstantFold: case EvalInfo::EM_EvaluateForOverflow: case EvalInfo::EM_IgnoreSideEffects: - case EvalInfo::EM_DesignatorFold: + case EvalInfo::EM_OffsetFold: // Leave it to IR generation. return Error(E); case EvalInfo::EM_ConstantExpressionUnevaluated: @@ -6857,6 +7347,8 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { // Reduce it to a constant now. return Success((Type & 2) ? 0 : -1, E); } + + llvm_unreachable("unexpected EvalMode"); } case Builtin::BI__builtin_bswap16: @@ -6990,20 +7482,25 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { } case Builtin::BIstrlen: + case Builtin::BIwcslen: // A call to strlen is not a constant expression. if (Info.getLangOpts().CPlusPlus11) Info.CCEDiag(E, diag::note_constexpr_invalid_function) - << /*isConstexpr*/0 << /*isConstructor*/0 << "'strlen'"; + << /*isConstexpr*/0 << /*isConstructor*/0 + << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'"); else Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); // Fall through. - case Builtin::BI__builtin_strlen: { + case Builtin::BI__builtin_strlen: + case Builtin::BI__builtin_wcslen: { // As an extension, we support __builtin_strlen() as a constant expression, // and support folding strlen() to a constant. LValue String; if (!EvaluatePointer(E->getArg(0), String, Info)) return false; + QualType CharTy = E->getArg(0)->getType()->getPointeeType(); + // Fast path: if it's a string literal, search the string value. if (const StringLiteral *S = dyn_cast_or_null<StringLiteral>( String.getLValueBase().dyn_cast<const Expr *>())) { @@ -7012,7 +7509,9 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { StringRef Str = S->getBytes(); int64_t Off = String.Offset.getQuantity(); if (Off >= 0 && (uint64_t)Off <= (uint64_t)Str.size() && - S->getCharByteWidth() == 1) { + S->getCharByteWidth() == 1 && + // FIXME: Add fast-path for wchar_t too. + Info.Ctx.hasSameUnqualifiedType(CharTy, Info.Ctx.CharTy)) { Str = Str.substr(Off); StringRef::size_type Pos = Str.find(0); @@ -7026,7 +7525,6 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { } // Slow path: scan the bytes of the string looking for the terminating 0. - QualType CharTy = E->getArg(0)->getType()->getPointeeType(); for (uint64_t Strlen = 0; /**/; ++Strlen) { APValue Char; if (!handleLValueToRValueConversion(Info, E, CharTy, String, Char) || @@ -7039,6 +7537,66 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { } } + case Builtin::BIstrcmp: + case Builtin::BIwcscmp: + case Builtin::BIstrncmp: + case Builtin::BIwcsncmp: + case Builtin::BImemcmp: + case Builtin::BIwmemcmp: + // A call to strlen is not a constant expression. + if (Info.getLangOpts().CPlusPlus11) + Info.CCEDiag(E, diag::note_constexpr_invalid_function) + << /*isConstexpr*/0 << /*isConstructor*/0 + << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'"); + else + Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); + // Fall through. + case Builtin::BI__builtin_strcmp: + case Builtin::BI__builtin_wcscmp: + case Builtin::BI__builtin_strncmp: + case Builtin::BI__builtin_wcsncmp: + case Builtin::BI__builtin_memcmp: + case Builtin::BI__builtin_wmemcmp: { + LValue String1, String2; + if (!EvaluatePointer(E->getArg(0), String1, Info) || + !EvaluatePointer(E->getArg(1), String2, Info)) + return false; + + QualType CharTy = E->getArg(0)->getType()->getPointeeType(); + + uint64_t MaxLength = uint64_t(-1); + if (BuiltinOp != Builtin::BIstrcmp && + BuiltinOp != Builtin::BIwcscmp && + BuiltinOp != Builtin::BI__builtin_strcmp && + BuiltinOp != Builtin::BI__builtin_wcscmp) { + APSInt N; + if (!EvaluateInteger(E->getArg(2), N, Info)) + return false; + MaxLength = N.getExtValue(); + } + bool StopAtNull = (BuiltinOp != Builtin::BImemcmp && + BuiltinOp != Builtin::BIwmemcmp && + BuiltinOp != Builtin::BI__builtin_memcmp && + BuiltinOp != Builtin::BI__builtin_wmemcmp); + for (; MaxLength; --MaxLength) { + APValue Char1, Char2; + if (!handleLValueToRValueConversion(Info, E, CharTy, String1, Char1) || + !handleLValueToRValueConversion(Info, E, CharTy, String2, Char2) || + !Char1.isInt() || !Char2.isInt()) + return false; + if (Char1.getInt() != Char2.getInt()) + return Success(Char1.getInt() < Char2.getInt() ? -1 : 1, E); + if (StopAtNull && !Char1.getInt()) + return Success(0, E); + assert(!(StopAtNull && !Char2.getInt())); + if (!HandleLValueArrayAdjustment(Info, E, String1, CharTy, 1) || + !HandleLValueArrayAdjustment(Info, E, String2, CharTy, 1)) + return false; + } + // We hit the strncmp / memcmp limit. + return Success(0, E); + } + case Builtin::BI__atomic_always_lock_free: case Builtin::BI__atomic_is_lock_free: case Builtin::BI__c11_atomic_is_lock_free: { @@ -7160,9 +7718,7 @@ class DataRecursiveIntBinOpEvaluator { enum { AnyExprKind, BinOpKind, BinOpVisitedLHSKind } Kind; Job() = default; - Job(Job &&J) - : E(J.E), LHSResult(J.LHSResult), Kind(J.Kind), - SpecEvalRAII(std::move(J.SpecEvalRAII)) {} + Job(Job &&) = default; void startSpeculativeEval(EvalInfo &Info) { SpecEvalRAII = SpeculativeEvaluationRAII(Info); @@ -8037,8 +8593,10 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_IntegralComplexToFloatingComplex: case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLEvent: + case CK_ZeroToOCLQueue: case CK_NonAtomicToAtomic: case CK_AddressSpaceConversion: + case CK_IntToOCLSampler: llvm_unreachable("invalid cast kind for integral value"); case CK_BitCast: @@ -8113,8 +8671,13 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { return true; } - APSInt AsInt = Info.Ctx.MakeIntValue(LV.getLValueOffset().getQuantity(), - SrcType); + uint64_t V; + if (LV.isNullPointer()) + V = Info.Ctx.getTargetNullPointerValue(SrcType); + else + V = LV.getLValueOffset().getQuantity(); + + APSInt AsInt = Info.Ctx.MakeIntValue(V, SrcType); return Success(HandleIntToIntCast(Info, E, DestType, SrcType, AsInt), E); } @@ -8528,8 +9091,10 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_CopyAndAutoreleaseBlockObject: case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLEvent: + case CK_ZeroToOCLQueue: case CK_NonAtomicToAtomic: case CK_AddressSpaceConversion: + case CK_IntToOCLSampler: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: @@ -9341,6 +9906,8 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::CompoundLiteralExprClass: case Expr::ExtVectorElementExprClass: case Expr::DesignatedInitExprClass: + case Expr::ArrayInitLoopExprClass: + case Expr::ArrayInitIndexExprClass: case Expr::NoInitExprClass: case Expr::DesignatedInitUpdateExprClass: case Expr::ImplicitValueInitExprClass: @@ -9877,5 +10444,5 @@ bool Expr::tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx, Expr::EvalStatus Status; EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold); - return ::tryEvaluateBuiltinObjectSize(this, Type, Info, Result); + return tryEvaluateBuiltinObjectSize(this, Type, Info, Result); } diff --git a/lib/AST/ExprObjC.cpp b/lib/AST/ExprObjC.cpp index 0936a81a597a0..31c1b3f156217 100644 --- a/lib/AST/ExprObjC.cpp +++ b/lib/AST/ExprObjC.cpp @@ -278,7 +278,7 @@ ObjCMessageExpr *ObjCMessageExpr::alloc(const ASTContext &C, unsigned NumArgs, unsigned NumStoredSelLocs) { return (ObjCMessageExpr *)C.Allocate( totalSizeToAlloc<void *, SourceLocation>(NumArgs + 1, NumStoredSelLocs), - llvm::AlignOf<ObjCMessageExpr>::Alignment); + alignof(ObjCMessageExpr)); } void ObjCMessageExpr::getSelectorLocs( diff --git a/lib/AST/ItaniumCXXABI.cpp b/lib/AST/ItaniumCXXABI.cpp index 8a2cc0fbee429..692a455eafc08 100644 --- a/lib/AST/ItaniumCXXABI.cpp +++ b/lib/AST/ItaniumCXXABI.cpp @@ -63,9 +63,10 @@ public: CallOperator->getType()->getAs<FunctionProtoType>(); ASTContext &Context = CallOperator->getASTContext(); + FunctionProtoType::ExtProtoInfo EPI; + EPI.Variadic = Proto->isVariadic(); QualType Key = - Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), - FunctionProtoType::ExtProtoInfo()); + Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), EPI); Key = Context.getCanonicalType(Key); return ++ManglingNumbers[Key->castAs<FunctionProtoType>()]; } @@ -141,14 +142,6 @@ public: void addCopyConstructorForExceptionObject(CXXRecordDecl *RD, CXXConstructorDecl *CD) override {} - void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD, - unsigned ParmIdx, Expr *DAE) override {} - - Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, - unsigned ParmIdx) override { - return nullptr; - } - void addTypedefNameForUnnamedTagDecl(TagDecl *TD, TypedefNameDecl *DD) override {} @@ -163,8 +156,9 @@ public: return nullptr; } - MangleNumberingContext *createMangleNumberingContext() const override { - return new ItaniumNumberingContext(); + std::unique_ptr<MangleNumberingContext> + createMangleNumberingContext() const override { + return llvm::make_unique<ItaniumNumberingContext>(); } }; } diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 694fde317542f..ab3e49d903cfa 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -405,12 +405,14 @@ public: CXXNameMangler(CXXNameMangler &Outer, raw_ostream &Out_) : Context(Outer.Context), Out(Out_), NullOut(false), Structor(Outer.Structor), StructorType(Outer.StructorType), - SeqID(Outer.SeqID), AbiTagsRoot(AbiTags) {} + SeqID(Outer.SeqID), FunctionTypeDepth(Outer.FunctionTypeDepth), + AbiTagsRoot(AbiTags), Substitutions(Outer.Substitutions) {} CXXNameMangler(CXXNameMangler &Outer, llvm::raw_null_ostream &Out_) : Context(Outer.Context), Out(Out_), NullOut(true), Structor(Outer.Structor), StructorType(Outer.StructorType), - SeqID(Outer.SeqID), AbiTagsRoot(AbiTags) {} + SeqID(Outer.SeqID), FunctionTypeDepth(Outer.FunctionTypeDepth), + AbiTagsRoot(AbiTags), Substitutions(Outer.Substitutions) {} #if MANGLE_CHECKER ~CXXNameMangler() { @@ -458,11 +460,15 @@ private: void addSubstitution(QualType T); void addSubstitution(TemplateName Template); void addSubstitution(uintptr_t Ptr); + // Destructive copy substitutions from other mangler. + void extendSubstitutions(CXXNameMangler* Other); void mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, bool recursive = false); void mangleUnresolvedName(NestedNameSpecifier *qualifier, DeclarationName name, + const TemplateArgumentLoc *TemplateArgs, + unsigned NumTemplateArgs, unsigned KnownArity = UnknownArity); void mangleFunctionEncodingBareType(const FunctionDecl *FD); @@ -487,6 +493,7 @@ private: void mangleUnscopedTemplateName(TemplateName, const AbiTagList *AdditionalAbiTags); void mangleSourceName(const IdentifierInfo *II); + void mangleRegCallName(const IdentifierInfo *II); void mangleSourceNameWithAbiTags( const NamedDecl *ND, const AbiTagList *AdditionalAbiTags = nullptr); void mangleLocalName(const Decl *D, @@ -537,6 +544,8 @@ private: NestedNameSpecifier *qualifier, NamedDecl *firstQualifierLookup, DeclarationName name, + const TemplateArgumentLoc *TemplateArgs, + unsigned NumTemplateArgs, unsigned knownArity); void mangleCastExpression(const Expr *E, StringRef CastEncoding); void mangleInitListElements(const InitListExpr *InitList); @@ -593,7 +602,7 @@ bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { return false; const VarDecl *VD = dyn_cast<VarDecl>(D); - if (VD) { + if (VD && !isa<DecompositionDecl>(D)) { // C variables are not mangled. if (VD->isExternC()) return false; @@ -685,6 +694,10 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { // Output name with implicit tags and function encoding from temporary buffer. mangleNameWithAbiTags(FD, &AdditionalAbiTags); Out << FunctionEncodingStream.str().substr(EncodingPositionStart); + + // Function encoding could create new substitutions so we have to add + // temp mangled substitutions to main mangler. + extendSubstitutions(&FunctionEncodingMangler); } void CXXNameMangler::mangleFunctionEncodingBareType(const FunctionDecl *FD) { @@ -1151,9 +1164,10 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, /// Mangle an unresolved-name, which is generally used for names which /// weren't resolved to specific entities. -void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier, - DeclarationName name, - unsigned knownArity) { +void CXXNameMangler::mangleUnresolvedName( + NestedNameSpecifier *qualifier, DeclarationName name, + const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, + unsigned knownArity) { if (qualifier) mangleUnresolvedPrefix(qualifier); switch (name.getNameKind()) { // <base-unresolved-name> ::= <simple-id> @@ -1181,6 +1195,11 @@ void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier, case DeclarationName::ObjCZeroArgSelector: llvm_unreachable("Can't mangle Objective-C selector names here!"); } + + // The <simple-id> and on <operator-name> productions end in an optional + // <template-args>. + if (TemplateArgs) + mangleTemplateArgs(TemplateArgs, NumTemplateArgs); } void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, @@ -1193,7 +1212,26 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // ::= <source-name> switch (Name.getNameKind()) { case DeclarationName::Identifier: { - if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) { + const IdentifierInfo *II = Name.getAsIdentifierInfo(); + + // We mangle decomposition declarations as the names of their bindings. + if (auto *DD = dyn_cast<DecompositionDecl>(ND)) { + // FIXME: Non-standard mangling for decomposition declarations: + // + // <unqualified-name> ::= DC <source-name>* E + // + // These can never be referenced across translation units, so we do + // not need a cross-vendor mangling for anything other than demanglers. + // Proposed on cxx-abi-dev on 2016-08-12 + Out << "DC"; + for (auto *BD : DD->bindings()) + mangleSourceName(BD->getDeclName().getAsIdentifierInfo()); + Out << 'E'; + writeAbiTags(ND, AdditionalAbiTags); + break; + } + + if (II) { // We must avoid conflicts between internally- and externally- // linked variable and function declaration names in the same TU: // void test() { extern void foo(); } @@ -1204,7 +1242,15 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, getEffectiveDeclContext(ND)->isFileContext()) Out << 'L'; - mangleSourceName(II); + auto *FD = dyn_cast<FunctionDecl>(ND); + bool IsRegCall = FD && + FD->getType()->castAs<FunctionType>()->getCallConv() == + clang::CC_X86RegCall; + if (IsRegCall) + mangleRegCallName(II); + else + mangleSourceName(II); + writeAbiTags(ND, AdditionalAbiTags); break; } @@ -1378,6 +1424,14 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, } } +void CXXNameMangler::mangleRegCallName(const IdentifierInfo *II) { + // <source-name> ::= <positive length number> __regcall3__ <identifier> + // <number> ::= [n] <non-negative decimal integer> + // <identifier> ::= <unqualified source code identifier> + Out << II->getLength() + sizeof("__regcall3__") - 1 << "__regcall3__" + << II->getName(); +} + void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) { // <source-name> ::= <positive length number> <identifier> // <number> ::= [n] <non-negative decimal integer> @@ -1471,7 +1525,7 @@ void CXXNameMangler::mangleLocalName(const Decl *D, // numbering will be local to the particular argument in which it appears // -- other default arguments do not affect its encoding. const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD); - if (CXXRD->isLambda()) { + if (CXXRD && CXXRD->isLambda()) { if (const ParmVarDecl *Parm = dyn_cast_or_null<ParmVarDecl>(CXXRD->getLambdaContextDecl())) { if (const FunctionDecl *Func @@ -1820,6 +1874,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: + case Type::ObjCTypeParam: case Type::Atomic: case Type::Pipe: llvm_unreachable("type is illegal as a nested name specifier"); @@ -2207,6 +2262,22 @@ void CXXNameMangler::mangleType(QualType T) { // they aren't written. // - Conversions on non-type template arguments need to be expressed, since // they can affect the mangling of sizeof/alignof. + // + // FIXME: This is wrong when mapping to the canonical type for a dependent + // type discards instantiation-dependent portions of the type, such as for: + // + // template<typename T, int N> void f(T (&)[sizeof(N)]); + // template<typename T> void f(T() throw(typename T::type)); (pre-C++17) + // + // It's also wrong in the opposite direction when instantiation-dependent, + // canonically-equivalent types differ in some irrelevant portion of inner + // type sugar. In such cases, we fail to form correct substitutions, eg: + // + // template<int N> void f(A<sizeof(N)> *, A<sizeof(N)> (*)); + // + // We should instead canonicalize the non-instantiation-dependent parts, + // regardless of whether the type as a whole is dependent or instantiation + // dependent. if (!T->isInstantiationDependentType() || T->isDependentType()) T = T.getCanonicalType(); else { @@ -2443,6 +2514,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) { case CC_X86Pascal: case CC_X86_64Win64: case CC_X86_64SysV: + case CC_X86RegCall: case CC_AAPCS: case CC_AAPCS_VFP: case CC_IntelOclBicc: @@ -2509,6 +2581,24 @@ void CXXNameMangler::mangleType(const FunctionProtoType *T) { // e.g. "const" in "int (A::*)() const". mangleQualifiers(Qualifiers::fromCVRMask(T->getTypeQuals())); + // Mangle instantiation-dependent exception-specification, if present, + // per cxx-abi-dev proposal on 2016-10-11. + if (T->hasInstantiationDependentExceptionSpec()) { + if (T->getExceptionSpecType() == EST_ComputedNoexcept) { + Out << "DO"; + mangleExpression(T->getNoexceptExpr()); + Out << "E"; + } else { + assert(T->getExceptionSpecType() == EST_Dynamic); + Out << "Dw"; + for (auto ExceptTy : T->exceptions()) + mangleType(ExceptTy); + Out << "E"; + } + } else if (T->isNothrow(getASTContext())) { + Out << "Do"; + } + Out << 'F'; // FIXME: We don't have enough information in the AST to produce the 'Y' @@ -3115,12 +3205,14 @@ void CXXNameMangler::mangleMemberExpr(const Expr *base, NestedNameSpecifier *qualifier, NamedDecl *firstQualifierLookup, DeclarationName member, + const TemplateArgumentLoc *TemplateArgs, + unsigned NumTemplateArgs, unsigned arity) { // <expression> ::= dt <expression> <unresolved-name> // ::= pt <expression> <unresolved-name> if (base) mangleMemberExprBase(base, isArrow); - mangleUnresolvedName(qualifier, member, arity); + mangleUnresolvedName(qualifier, member, TemplateArgs, NumTemplateArgs, arity); } /// Look at the callee of the given call expression and determine if @@ -3209,6 +3301,8 @@ recurse: case Expr::AddrLabelExprClass: case Expr::DesignatedInitUpdateExprClass: case Expr::ImplicitValueInitExprClass: + case Expr::ArrayInitLoopExprClass: + case Expr::ArrayInitIndexExprClass: case Expr::NoInitExprClass: case Expr::ParenListExprClass: case Expr::LambdaExprClass: @@ -3418,7 +3512,9 @@ recurse: const MemberExpr *ME = cast<MemberExpr>(E); mangleMemberExpr(ME->getBase(), ME->isArrow(), ME->getQualifier(), nullptr, - ME->getMemberDecl()->getDeclName(), Arity); + ME->getMemberDecl()->getDeclName(), + ME->getTemplateArgs(), ME->getNumTemplateArgs(), + Arity); break; } @@ -3426,9 +3522,9 @@ recurse: const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E); mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(), ME->isArrow(), ME->getQualifier(), nullptr, - ME->getMemberName(), Arity); - if (ME->hasExplicitTemplateArgs()) - mangleTemplateArgs(ME->getTemplateArgs(), ME->getNumTemplateArgs()); + ME->getMemberName(), + ME->getTemplateArgs(), ME->getNumTemplateArgs(), + Arity); break; } @@ -3438,21 +3534,17 @@ recurse: mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(), ME->isArrow(), ME->getQualifier(), ME->getFirstQualifierFoundInScope(), - ME->getMember(), Arity); - if (ME->hasExplicitTemplateArgs()) - mangleTemplateArgs(ME->getTemplateArgs(), ME->getNumTemplateArgs()); + ME->getMember(), + ME->getTemplateArgs(), ME->getNumTemplateArgs(), + Arity); break; } case Expr::UnresolvedLookupExprClass: { const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E); - mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), Arity); - - // All the <unresolved-name> productions end in a - // base-unresolved-name, where <template-args> are just tacked - // onto the end. - if (ULE->hasExplicitTemplateArgs()) - mangleTemplateArgs(ULE->getTemplateArgs(), ULE->getNumTemplateArgs()); + mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), + ULE->getTemplateArgs(), ULE->getNumTemplateArgs(), + Arity); break; } @@ -3707,7 +3799,10 @@ recurse: case Expr::CXXOperatorCallExprClass: { const CXXOperatorCallExpr *CE = cast<CXXOperatorCallExpr>(E); unsigned NumArgs = CE->getNumArgs(); - mangleOperatorName(CE->getOperator(), /*Arity=*/NumArgs); + // A CXXOperatorCallExpr for OO_Arrow models only semantics, not syntax + // (the enclosing MemberExpr covers the syntactic portion). + if (CE->getOperator() != OO_Arrow) + mangleOperatorName(CE->getOperator(), /*Arity=*/NumArgs); // Mangle the arguments. for (unsigned i = 0; i != NumArgs; ++i) mangleExpression(CE->getArg(i)); @@ -3768,13 +3863,9 @@ recurse: case Expr::DependentScopeDeclRefExprClass: { const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E); - mangleUnresolvedName(DRE->getQualifier(), DRE->getDeclName(), Arity); - - // All the <unresolved-name> productions end in a - // base-unresolved-name, where <template-args> are just tacked - // onto the end. - if (DRE->hasExplicitTemplateArgs()) - mangleTemplateArgs(DRE->getTemplateArgs(), DRE->getNumTemplateArgs()); + mangleUnresolvedName(DRE->getQualifier(), DRE->getDeclName(), + DRE->getTemplateArgs(), DRE->getNumTemplateArgs(), + Arity); break; } @@ -4406,6 +4497,14 @@ void CXXNameMangler::addSubstitution(uintptr_t Ptr) { Substitutions[Ptr] = SeqID++; } +void CXXNameMangler::extendSubstitutions(CXXNameMangler* Other) { + assert(Other->SeqID >= SeqID && "Must be superset of substitutions!"); + if (Other->SeqID > SeqID) { + Substitutions.swap(Other->Substitutions); + SeqID = Other->SeqID; + } +} + CXXNameMangler::AbiTagList CXXNameMangler::makeFunctionReturnTypeTags(const FunctionDecl *FD) { // When derived abi tags are disabled there is no need to make any list. diff --git a/lib/AST/Mangle.cpp b/lib/AST/Mangle.cpp index ee241732e8ad2..05dd886adcefc 100644 --- a/lib/AST/Mangle.cpp +++ b/lib/AST/Mangle.cpp @@ -52,6 +52,7 @@ void MangleContext::anchor() { } enum CCMangling { CCM_Other, CCM_Fast, + CCM_RegCall, CCM_Vector, CCM_Std }; @@ -152,6 +153,8 @@ void MangleContext::mangleName(const NamedDecl *D, raw_ostream &Out) { Out << '_'; else if (CC == CCM_Fast) Out << '@'; + else if (CC == CCM_RegCall) + Out << "__regcall3__"; if (!MCXX) Out << D->getIdentifier()->getName(); diff --git a/lib/AST/MicrosoftCXXABI.cpp b/lib/AST/MicrosoftCXXABI.cpp index 3ae04538d6267..73324e40f3b10 100644 --- a/lib/AST/MicrosoftCXXABI.cpp +++ b/lib/AST/MicrosoftCXXABI.cpp @@ -67,8 +67,6 @@ public: class MicrosoftCXXABI : public CXXABI { ASTContext &Context; llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor; - llvm::SmallDenseMap<std::pair<const CXXConstructorDecl *, unsigned>, Expr *> - CtorToDefaultArgExpr; llvm::SmallDenseMap<TagDecl *, DeclaratorDecl *> UnnamedTagDeclToDeclaratorDecl; @@ -92,16 +90,6 @@ public: llvm_unreachable("unapplicable to the MS ABI"); } - void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD, - unsigned ParmIdx, Expr *DAE) override { - CtorToDefaultArgExpr[std::make_pair(CD, ParmIdx)] = DAE; - } - - Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, - unsigned ParmIdx) override { - return CtorToDefaultArgExpr[std::make_pair(CD, ParmIdx)]; - } - const CXXConstructorDecl * getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override { return RecordToCopyCtor[RD]; @@ -143,8 +131,9 @@ public: const_cast<TagDecl *>(TD->getCanonicalDecl())); } - MangleNumberingContext *createMangleNumberingContext() const override { - return new MicrosoftNumberingContext(); + std::unique_ptr<MangleNumberingContext> + createMangleNumberingContext() const override { + return llvm::make_unique<MicrosoftNumberingContext>(); } }; } diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 351997e02a9d1..911b8b471a05c 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -66,6 +66,16 @@ struct msvc_hashing_ostream : public llvm::raw_svector_ostream { } }; +static const DeclContext * +getLambdaDefaultArgumentDeclContext(const Decl *D) { + if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) + if (RD->isLambda()) + if (const auto *Parm = + dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl())) + return Parm->getDeclContext(); + return nullptr; +} + /// \brief Retrieve the declaration context that should be used when mangling /// the given declaration. static const DeclContext *getEffectiveDeclContext(const Decl *D) { @@ -75,12 +85,8 @@ static const DeclContext *getEffectiveDeclContext(const Decl *D) { // not the case: the lambda closure type ends up living in the context // where the function itself resides, because the function declaration itself // had not yet been created. Fix the context here. - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { - if (RD->isLambda()) - if (ParmVarDecl *ContextParam = - dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl())) - return ContextParam->getDeclContext(); - } + if (const auto *LDADC = getLambdaDefaultArgumentDeclContext(D)) + return LDADC; // Perform the same check for block literals. if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { @@ -112,14 +118,6 @@ static const FunctionDecl *getStructor(const NamedDecl *ND) { return FD; } -static bool isLambda(const NamedDecl *ND) { - const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND); - if (!Record) - return false; - - return Record->isLambda(); -} - /// MicrosoftMangleContextImpl - Overrides the default MangleContext for the /// Microsoft Visual C++ ABI. class MicrosoftMangleContextImpl : public MicrosoftMangleContext { @@ -200,9 +198,11 @@ public: // Lambda closure types are already numbered, give out a phony number so // that they demangle nicely. - if (isLambda(ND)) { - disc = 1; - return true; + if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) { + if (RD->isLambda()) { + disc = 1; + return true; + } } // Use the canonical number for externally visible decls. @@ -394,7 +394,8 @@ bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { if (!getASTContext().getLangOpts().CPlusPlus) return false; - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + const VarDecl *VD = dyn_cast<VarDecl>(D); + if (VD && !isa<DecompositionDecl>(D)) { // C variables are not mangled. if (VD->isExternC()) return false; @@ -780,6 +781,21 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, } } + if (const DecompositionDecl *DD = dyn_cast<DecompositionDecl>(ND)) { + // FIXME: Invented mangling for decomposition declarations: + // [X,Y,Z] + // where X,Y,Z are the names of the bindings. + llvm::SmallString<128> Name("["); + for (auto *BD : DD->bindings()) { + if (Name.size() > 1) + Name += ','; + Name += BD->getDeclName().getAsIdentifierInfo()->getName(); + } + Name += ']'; + mangleSourceName(Name); + break; + } + if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) { // We must have an anonymous union or struct declaration. const CXXRecordDecl *RD = VD->getType()->getAsCXXRecordDecl(); @@ -808,9 +824,24 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) { if (Record->isLambda()) { llvm::SmallString<10> Name("<lambda_"); + + Decl *LambdaContextDecl = Record->getLambdaContextDecl(); + unsigned LambdaManglingNumber = Record->getLambdaManglingNumber(); unsigned LambdaId; - if (Record->getLambdaManglingNumber()) - LambdaId = Record->getLambdaManglingNumber(); + const ParmVarDecl *Parm = + dyn_cast_or_null<ParmVarDecl>(LambdaContextDecl); + const FunctionDecl *Func = + Parm ? dyn_cast<FunctionDecl>(Parm->getDeclContext()) : nullptr; + + if (Func) { + unsigned DefaultArgNo = + Func->getNumParams() - Parm->getFunctionScopeIndex(); + Name += llvm::utostr(DefaultArgNo); + Name += "_"; + } + + if (LambdaManglingNumber) + LambdaId = LambdaManglingNumber; else LambdaId = Context.getLambdaId(Record); @@ -818,25 +849,42 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, Name += ">"; mangleSourceName(Name); + + // If the context of a closure type is an initializer for a class + // member (static or nonstatic), it is encoded in a qualified name. + if (LambdaManglingNumber && LambdaContextDecl) { + if ((isa<VarDecl>(LambdaContextDecl) || + isa<FieldDecl>(LambdaContextDecl)) && + LambdaContextDecl->getDeclContext()->isRecord()) { + mangleUnqualifiedName(cast<NamedDecl>(LambdaContextDecl)); + } + } break; } } - llvm::SmallString<64> Name("<unnamed-type-"); + llvm::SmallString<64> Name; if (DeclaratorDecl *DD = Context.getASTContext().getDeclaratorForUnnamedTagDecl(TD)) { // Anonymous types without a name for linkage purposes have their // declarator mangled in if they have one. + Name += "<unnamed-type-"; Name += DD->getName(); } else if (TypedefNameDecl *TND = Context.getASTContext().getTypedefNameForUnnamedTagDecl( TD)) { // Anonymous types without a name for linkage purposes have their // associate typedef mangled in if they have one. + Name += "<unnamed-type-"; Name += TND->getName(); + } else if (auto *ED = dyn_cast<EnumDecl>(TD)) { + auto EnumeratorI = ED->enumerator_begin(); + assert(EnumeratorI != ED->enumerator_end()); + Name += "<unnamed-enum-"; + Name += EnumeratorI->getName(); } else { // Otherwise, number the types using a $S prefix. - Name += "$S"; + Name += "<unnamed-type-$S"; Name += llvm::utostr(Context.getAnonymousStructId(TD) + 1); } Name += ">"; @@ -921,7 +969,6 @@ void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) { // for how this should be done. Out << "__block_invoke" << Context.getBlockId(BD, false); Out << '@'; - continue; } else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) { mangleObjCMethodName(Method); } else if (isa<NamedDecl>(DC)) { @@ -929,8 +976,15 @@ void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { mangle(FD, "?"); break; - } else + } else { mangleUnqualifiedName(ND); + // Lambdas in default arguments conceptually belong to the function the + // parameter corresponds to. + if (const auto *LDADC = getLambdaDefaultArgumentDeclContext(ND)) { + DC = LDADC; + continue; + } + } } DC = DC->getParent(); } @@ -1073,6 +1127,8 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, case OO_Array_New: Out << "?_U"; break; // <operator-name> ::= ?_V # delete[] case OO_Array_Delete: Out << "?_V"; break; + // <operator-name> ::= ?__L # co_await + case OO_Coawait: Out << "?__L"; break; case OO_Conditional: { DiagnosticsEngine &Diags = Context.getDiags(); @@ -1082,14 +1138,6 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, break; } - case OO_Coawait: { - DiagnosticsEngine &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle this operator co_await yet"); - Diags.Report(Loc, DiagID); - break; - } - case OO_None: case NUM_OVERLOADED_OPERATORS: llvm_unreachable("Not an overloaded operator"); @@ -1993,6 +2041,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) { // ::= I # __fastcall // ::= J # __export __fastcall // ::= Q # __vectorcall + // ::= w # __regcall // The 'export' calling conventions are from a bygone era // (*cough*Win16*cough*) when functions were declared for export with // that keyword. (It didn't actually export them, it just made them so @@ -2010,6 +2059,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) { case CC_X86StdCall: Out << 'G'; break; case CC_X86FastCall: Out << 'I'; break; case CC_X86VectorCall: Out << 'Q'; break; + case CC_X86RegCall: Out << 'w'; break; } } void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) { diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp index 82809d7ea7b53..514c7c9f5b338 100644 --- a/lib/AST/NestedNameSpecifier.cpp +++ b/lib/AST/NestedNameSpecifier.cpp @@ -34,8 +34,8 @@ NestedNameSpecifier::FindOrInsert(const ASTContext &Context, NestedNameSpecifier *NNS = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos); if (!NNS) { - NNS = new (Context, llvm::alignOf<NestedNameSpecifier>()) - NestedNameSpecifier(Mockup); + NNS = + new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(Mockup); Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos); } @@ -113,8 +113,7 @@ NestedNameSpecifier * NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) { if (!Context.GlobalNestedNameSpecifier) Context.GlobalNestedNameSpecifier = - new (Context, llvm::alignOf<NestedNameSpecifier>()) - NestedNameSpecifier(); + new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(); return Context.GlobalNestedNameSpecifier; } @@ -155,7 +154,7 @@ NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { /// \brief Retrieve the namespace stored in this nested name specifier. NamespaceDecl *NestedNameSpecifier::getAsNamespace() const { - if (Prefix.getInt() == StoredDecl) + if (Prefix.getInt() == StoredDecl) return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier)); return nullptr; @@ -163,7 +162,7 @@ NamespaceDecl *NestedNameSpecifier::getAsNamespace() const { /// \brief Retrieve the namespace alias stored in this nested name specifier. NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const { - if (Prefix.getInt() == StoredDecl) + if (Prefix.getInt() == StoredDecl) return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier)); return nullptr; @@ -687,7 +686,7 @@ NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const { // FIXME: After copying the source-location information, should we free // our (temporary) buffer and adopt the ASTContext-allocated memory? // Doing so would optimize repeated calls to getWithLocInContext(). - void *Mem = Context.Allocate(BufferSize, llvm::alignOf<void *>()); + void *Mem = Context.Allocate(BufferSize, alignof(void *)); memcpy(Mem, Buffer, BufferSize); return NestedNameSpecifierLoc(Representation, Mem); } diff --git a/lib/AST/OpenMPClause.cpp b/lib/AST/OpenMPClause.cpp index d04ba727bb059..a28b9f3b6d647 100644 --- a/lib/AST/OpenMPClause.cpp +++ b/lib/AST/OpenMPClause.cpp @@ -732,38 +732,113 @@ OMPFromClause *OMPFromClause::CreateEmpty(const ASTContext &C, unsigned NumVars, NumComponentLists, NumComponents); } -OMPUseDevicePtrClause *OMPUseDevicePtrClause::Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc, - ArrayRef<Expr *> VL) { - void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size())); - OMPUseDevicePtrClause *Clause = - new (Mem) OMPUseDevicePtrClause(StartLoc, LParenLoc, EndLoc, VL.size()); - Clause->setVarRefs(VL); +void OMPUseDevicePtrClause::setPrivateCopies(ArrayRef<Expr *> VL) { + assert(VL.size() == varlist_size() && + "Number of private copies is not the same as the preallocated buffer"); + std::copy(VL.begin(), VL.end(), varlist_end()); +} + +void OMPUseDevicePtrClause::setInits(ArrayRef<Expr *> VL) { + assert(VL.size() == varlist_size() && + "Number of inits is not the same as the preallocated buffer"); + std::copy(VL.begin(), VL.end(), getPrivateCopies().end()); +} + +OMPUseDevicePtrClause *OMPUseDevicePtrClause::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> Vars, ArrayRef<Expr *> PrivateVars, + ArrayRef<Expr *> Inits, ArrayRef<ValueDecl *> Declarations, + MappableExprComponentListsRef ComponentLists) { + unsigned NumVars = Vars.size(); + unsigned NumUniqueDeclarations = + getUniqueDeclarationsTotalNumber(Declarations); + unsigned NumComponentLists = ComponentLists.size(); + unsigned NumComponents = getComponentsTotalNumber(ComponentLists); + + // We need to allocate: + // 3 x NumVars x Expr* - we have an original list expression for each clause + // list entry and an equal number of private copies and inits. + // NumUniqueDeclarations x ValueDecl* - unique base declarations associated + // with each component list. + // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the + // number of lists for each unique declaration and the size of each component + // list. + // NumComponents x MappableComponent - the total of all the components in all + // the lists. + void *Mem = C.Allocate( + totalSizeToAlloc<Expr *, ValueDecl *, unsigned, + OMPClauseMappableExprCommon::MappableComponent>( + 3 * NumVars, NumUniqueDeclarations, + NumUniqueDeclarations + NumComponentLists, NumComponents)); + + OMPUseDevicePtrClause *Clause = new (Mem) OMPUseDevicePtrClause( + StartLoc, LParenLoc, EndLoc, NumVars, NumUniqueDeclarations, + NumComponentLists, NumComponents); + + Clause->setVarRefs(Vars); + Clause->setPrivateCopies(PrivateVars); + Clause->setInits(Inits); + Clause->setClauseInfo(Declarations, ComponentLists); return Clause; } -OMPUseDevicePtrClause *OMPUseDevicePtrClause::CreateEmpty(const ASTContext &C, - unsigned N) { - void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N)); - return new (Mem) OMPUseDevicePtrClause(N); +OMPUseDevicePtrClause *OMPUseDevicePtrClause::CreateEmpty( + const ASTContext &C, unsigned NumVars, unsigned NumUniqueDeclarations, + unsigned NumComponentLists, unsigned NumComponents) { + void *Mem = C.Allocate( + totalSizeToAlloc<Expr *, ValueDecl *, unsigned, + OMPClauseMappableExprCommon::MappableComponent>( + 3 * NumVars, NumUniqueDeclarations, + NumUniqueDeclarations + NumComponentLists, NumComponents)); + return new (Mem) OMPUseDevicePtrClause(NumVars, NumUniqueDeclarations, + NumComponentLists, NumComponents); } -OMPIsDevicePtrClause *OMPIsDevicePtrClause::Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc, - ArrayRef<Expr *> VL) { - void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size())); - OMPIsDevicePtrClause *Clause = - new (Mem) OMPIsDevicePtrClause(StartLoc, LParenLoc, EndLoc, VL.size()); - Clause->setVarRefs(VL); +OMPIsDevicePtrClause * +OMPIsDevicePtrClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + ArrayRef<Expr *> Vars, + ArrayRef<ValueDecl *> Declarations, + MappableExprComponentListsRef ComponentLists) { + unsigned NumVars = Vars.size(); + unsigned NumUniqueDeclarations = + getUniqueDeclarationsTotalNumber(Declarations); + unsigned NumComponentLists = ComponentLists.size(); + unsigned NumComponents = getComponentsTotalNumber(ComponentLists); + + // We need to allocate: + // NumVars x Expr* - we have an original list expression for each clause list + // entry. + // NumUniqueDeclarations x ValueDecl* - unique base declarations associated + // with each component list. + // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the + // number of lists for each unique declaration and the size of each component + // list. + // NumComponents x MappableComponent - the total of all the components in all + // the lists. + void *Mem = C.Allocate( + totalSizeToAlloc<Expr *, ValueDecl *, unsigned, + OMPClauseMappableExprCommon::MappableComponent>( + NumVars, NumUniqueDeclarations, + NumUniqueDeclarations + NumComponentLists, NumComponents)); + + OMPIsDevicePtrClause *Clause = new (Mem) OMPIsDevicePtrClause( + StartLoc, LParenLoc, EndLoc, NumVars, NumUniqueDeclarations, + NumComponentLists, NumComponents); + + Clause->setVarRefs(Vars); + Clause->setClauseInfo(Declarations, ComponentLists); return Clause; } -OMPIsDevicePtrClause *OMPIsDevicePtrClause::CreateEmpty(const ASTContext &C, - unsigned N) { - void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N)); - return new (Mem) OMPIsDevicePtrClause(N); +OMPIsDevicePtrClause *OMPIsDevicePtrClause::CreateEmpty( + const ASTContext &C, unsigned NumVars, unsigned NumUniqueDeclarations, + unsigned NumComponentLists, unsigned NumComponents) { + void *Mem = C.Allocate( + totalSizeToAlloc<Expr *, ValueDecl *, unsigned, + OMPClauseMappableExprCommon::MappableComponent>( + NumVars, NumUniqueDeclarations, + NumUniqueDeclarations + NumComponentLists, NumComponents)); + return new (Mem) OMPIsDevicePtrClause(NumVars, NumUniqueDeclarations, + NumComponentLists, NumComponents); } diff --git a/lib/AST/RawCommentList.cpp b/lib/AST/RawCommentList.cpp index 8317f76b8569f..881a7d9c61bee 100644 --- a/lib/AST/RawCommentList.cpp +++ b/lib/AST/RawCommentList.cpp @@ -175,8 +175,8 @@ StringRef RawComment::getRawTextSlow(const SourceManager &SourceMgr) const { } const char *RawComment::extractBriefText(const ASTContext &Context) const { - // Make sure that RawText is valid. - getRawText(Context.getSourceManager()); + // Lazily initialize RawText using the accessor before using it. + (void)getRawText(Context.getSourceManager()); // Since we will be copying the resulting text, all allocations made during // parsing are garbage after resulting string is formed. Thus we can use @@ -202,8 +202,8 @@ const char *RawComment::extractBriefText(const ASTContext &Context) const { comments::FullComment *RawComment::parse(const ASTContext &Context, const Preprocessor *PP, const Decl *D) const { - // Make sure that RawText is valid. - getRawText(Context.getSourceManager()); + // Lazily initialize RawText using the accessor before using it. + (void)getRawText(Context.getSourceManager()); comments::Lexer L(Context.getAllocator(), Context.getDiagnostics(), Context.getCommentCommandTraits(), @@ -334,4 +334,3 @@ void RawCommentList::addDeserializedComments(ArrayRef<RawComment *> Deserialized BeforeThanCompare<RawComment>(SourceMgr)); std::swap(Comments, MergedComments); } - diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 75c076399511e..697cdc3fb3608 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -315,7 +315,7 @@ AttributedStmt *AttributedStmt::Create(const ASTContext &C, SourceLocation Loc, Stmt *SubStmt) { assert(!Attrs.empty() && "Attrs should not be empty"); void *Mem = C.Allocate(sizeof(AttributedStmt) + sizeof(Attr *) * Attrs.size(), - llvm::alignOf<AttributedStmt>()); + alignof(AttributedStmt)); return new (Mem) AttributedStmt(Loc, Attrs, SubStmt); } @@ -323,7 +323,7 @@ AttributedStmt *AttributedStmt::CreateEmpty(const ASTContext &C, unsigned NumAttrs) { assert(NumAttrs > 0 && "NumAttrs should be greater than zero"); void *Mem = C.Allocate(sizeof(AttributedStmt) + sizeof(Attr *) * NumAttrs, - llvm::alignOf<AttributedStmt>()); + alignof(AttributedStmt)); return new (Mem) AttributedStmt(EmptyShell(), NumAttrs); } @@ -533,15 +533,17 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces, DiagOffs = CurPtr-StrStart-1; return diag::err_asm_invalid_escape; } - + // Handle escaped char and continue looping over the asm string. char EscapedChar = *CurPtr++; - if (EscapedChar == '%') { // %% -> % - // Escaped percentage sign. - CurStringPiece += '%'; + switch (EscapedChar) { + default: + break; + case '%': // %% -> % + case '{': // %{ -> { + case '}': // %} -> } + CurStringPiece += EscapedChar; continue; - } - - if (EscapedChar == '=') { // %= -> Generate an unique ID. + case '=': // %= -> Generate a unique ID. CurStringPiece += "${:uid}"; continue; } @@ -794,6 +796,10 @@ void IfStmt::setConditionVariable(const ASTContext &C, VarDecl *V) { VarRange.getEnd()); } +bool IfStmt::isObjCAvailabilityCheck() const { + return isa<ObjCAvailabilityCheckExpr>(SubExprs[COND]); +} + ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP, SourceLocation RP) @@ -998,7 +1004,7 @@ CapturedStmt::Capture *CapturedStmt::getStoredCaptures() const { unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1); // Offset of the first Capture object. - unsigned FirstCaptureOffset = llvm::alignTo(Size, llvm::alignOf<Capture>()); + unsigned FirstCaptureOffset = llvm::alignTo(Size, alignof(Capture)); return reinterpret_cast<Capture *>( reinterpret_cast<char *>(const_cast<CapturedStmt *>(this)) @@ -1055,7 +1061,7 @@ CapturedStmt *CapturedStmt::Create(const ASTContext &Context, Stmt *S, unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (Captures.size() + 1); if (!Captures.empty()) { // Realign for the following Capture array. - Size = llvm::alignTo(Size, llvm::alignOf<Capture>()); + Size = llvm::alignTo(Size, alignof(Capture)); Size += sizeof(Capture) * Captures.size(); } @@ -1068,7 +1074,7 @@ CapturedStmt *CapturedStmt::CreateDeserialized(const ASTContext &Context, unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1); if (NumCaptures > 0) { // Realign for the following Capture array. - Size = llvm::alignTo(Size, llvm::alignOf<Capture>()); + Size = llvm::alignTo(Size, alignof(Capture)); Size += sizeof(Capture) * NumCaptures; } diff --git a/lib/AST/StmtCXX.cpp b/lib/AST/StmtCXX.cpp index 4692db84b505d..4a04fc2112621 100644 --- a/lib/AST/StmtCXX.cpp +++ b/lib/AST/StmtCXX.cpp @@ -28,7 +28,7 @@ CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, SourceLocation tryLoc, std::size_t Size = sizeof(CXXTryStmt); Size += ((handlers.size() + 1) * sizeof(Stmt *)); - void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>()); + void *Mem = C.Allocate(Size, alignof(CXXTryStmt)); return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers); } @@ -37,7 +37,7 @@ CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, EmptyShell Empty, std::size_t Size = sizeof(CXXTryStmt); Size += ((numHandlers + 1) * sizeof(Stmt *)); - void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>()); + void *Mem = C.Allocate(Size, alignof(CXXTryStmt)); return new (Mem) CXXTryStmt(Empty, numHandlers); } diff --git a/lib/AST/StmtObjC.cpp b/lib/AST/StmtObjC.cpp index a77550c7605d3..eea03f64c2fe5 100644 --- a/lib/AST/StmtObjC.cpp +++ b/lib/AST/StmtObjC.cpp @@ -50,7 +50,7 @@ ObjCAtTryStmt *ObjCAtTryStmt::Create(const ASTContext &Context, unsigned Size = sizeof(ObjCAtTryStmt) + (1 + NumCatchStmts + (atFinallyStmt != nullptr)) * sizeof(Stmt *); - void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>()); + void *Mem = Context.Allocate(Size, alignof(ObjCAtTryStmt)); return new (Mem) ObjCAtTryStmt(atTryLoc, atTryStmt, CatchStmts, NumCatchStmts, atFinallyStmt); } @@ -60,7 +60,7 @@ ObjCAtTryStmt *ObjCAtTryStmt::CreateEmpty(const ASTContext &Context, bool HasFinally) { unsigned Size = sizeof(ObjCAtTryStmt) + (1 + NumCatchStmts + HasFinally) * sizeof(Stmt *); - void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>()); + void *Mem = Context.Allocate(Size, alignof(ObjCAtTryStmt)); return new (Mem) ObjCAtTryStmt(EmptyShell(), NumCatchStmts, HasFinally); } diff --git a/lib/AST/StmtOpenMP.cpp b/lib/AST/StmtOpenMP.cpp index f1ddedb2b0f2d..0a90740162b98 100644 --- a/lib/AST/StmtOpenMP.cpp +++ b/lib/AST/StmtOpenMP.cpp @@ -58,7 +58,7 @@ OMPParallelDirective *OMPParallelDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) { unsigned Size = - llvm::alignTo(sizeof(OMPParallelDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPParallelDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPParallelDirective *Dir = @@ -73,7 +73,7 @@ OMPParallelDirective *OMPParallelDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPParallelDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPParallelDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPParallelDirective(NumClauses); @@ -84,8 +84,7 @@ OMPSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs) { - unsigned Size = - llvm::alignTo(sizeof(OMPSimdDirective), llvm::alignOf<OMPClause *>()); + unsigned Size = llvm::alignTo(sizeof(OMPSimdDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd)); @@ -113,8 +112,7 @@ OMPSimdDirective *OMPSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = - llvm::alignTo(sizeof(OMPSimdDirective), llvm::alignOf<OMPClause *>()); + unsigned Size = llvm::alignTo(sizeof(OMPSimdDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd)); @@ -126,8 +124,7 @@ OMPForDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel) { - unsigned Size = - llvm::alignTo(sizeof(OMPForDirective), llvm::alignOf<OMPClause *>()); + unsigned Size = llvm::alignTo(sizeof(OMPForDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for)); @@ -166,8 +163,7 @@ OMPForDirective *OMPForDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = - llvm::alignTo(sizeof(OMPForDirective), llvm::alignOf<OMPClause *>()); + unsigned Size = llvm::alignTo(sizeof(OMPForDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for)); @@ -180,7 +176,7 @@ OMPForSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs) { unsigned Size = - llvm::alignTo(sizeof(OMPForSimdDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPForSimdDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd)); @@ -219,7 +215,7 @@ OMPForSimdDirective *OMPForSimdDirective::CreateEmpty(const ASTContext &C, unsigned CollapsedNum, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPForSimdDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPForSimdDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd)); @@ -230,7 +226,7 @@ OMPSectionsDirective *OMPSectionsDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) { unsigned Size = - llvm::alignTo(sizeof(OMPSectionsDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPSectionsDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPSectionsDirective *Dir = @@ -245,7 +241,7 @@ OMPSectionsDirective *OMPSectionsDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPSectionsDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPSectionsDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPSectionsDirective(NumClauses); @@ -256,8 +252,7 @@ OMPSectionDirective *OMPSectionDirective::Create(const ASTContext &C, SourceLocation EndLoc, Stmt *AssociatedStmt, bool HasCancel) { - unsigned Size = - llvm::alignTo(sizeof(OMPSectionDirective), llvm::alignOf<Stmt *>()); + unsigned Size = llvm::alignTo(sizeof(OMPSectionDirective), alignof(Stmt *)); void *Mem = C.Allocate(Size + sizeof(Stmt *)); OMPSectionDirective *Dir = new (Mem) OMPSectionDirective(StartLoc, EndLoc); Dir->setAssociatedStmt(AssociatedStmt); @@ -267,8 +262,7 @@ OMPSectionDirective *OMPSectionDirective::Create(const ASTContext &C, OMPSectionDirective *OMPSectionDirective::CreateEmpty(const ASTContext &C, EmptyShell) { - unsigned Size = - llvm::alignTo(sizeof(OMPSectionDirective), llvm::alignOf<Stmt *>()); + unsigned Size = llvm::alignTo(sizeof(OMPSectionDirective), alignof(Stmt *)); void *Mem = C.Allocate(Size + sizeof(Stmt *)); return new (Mem) OMPSectionDirective(); } @@ -279,7 +273,7 @@ OMPSingleDirective *OMPSingleDirective::Create(const ASTContext &C, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { unsigned Size = - llvm::alignTo(sizeof(OMPSingleDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPSingleDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPSingleDirective *Dir = @@ -293,7 +287,7 @@ OMPSingleDirective *OMPSingleDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPSingleDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPSingleDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPSingleDirective(NumClauses); @@ -303,8 +297,7 @@ OMPMasterDirective *OMPMasterDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt) { - unsigned Size = - llvm::alignTo(sizeof(OMPMasterDirective), llvm::alignOf<Stmt *>()); + unsigned Size = llvm::alignTo(sizeof(OMPMasterDirective), alignof(Stmt *)); void *Mem = C.Allocate(Size + sizeof(Stmt *)); OMPMasterDirective *Dir = new (Mem) OMPMasterDirective(StartLoc, EndLoc); Dir->setAssociatedStmt(AssociatedStmt); @@ -313,8 +306,7 @@ OMPMasterDirective *OMPMasterDirective::Create(const ASTContext &C, OMPMasterDirective *OMPMasterDirective::CreateEmpty(const ASTContext &C, EmptyShell) { - unsigned Size = - llvm::alignTo(sizeof(OMPMasterDirective), llvm::alignOf<Stmt *>()); + unsigned Size = llvm::alignTo(sizeof(OMPMasterDirective), alignof(Stmt *)); void *Mem = C.Allocate(Size + sizeof(Stmt *)); return new (Mem) OMPMasterDirective(); } @@ -324,7 +316,7 @@ OMPCriticalDirective *OMPCriticalDirective::Create( SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { unsigned Size = - llvm::alignTo(sizeof(OMPCriticalDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPCriticalDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPCriticalDirective *Dir = @@ -338,7 +330,7 @@ OMPCriticalDirective *OMPCriticalDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPCriticalDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPCriticalDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPCriticalDirective(NumClauses); @@ -348,8 +340,8 @@ OMPParallelForDirective *OMPParallelForDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel) { - unsigned Size = llvm::alignTo(sizeof(OMPParallelForDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPParallelForDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for)); @@ -387,8 +379,8 @@ OMPParallelForDirective *OMPParallelForDirective::Create( OMPParallelForDirective * OMPParallelForDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = llvm::alignTo(sizeof(OMPParallelForDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPParallelForDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for)); @@ -399,8 +391,8 @@ OMPParallelForSimdDirective *OMPParallelForSimdDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs) { - unsigned Size = llvm::alignTo(sizeof(OMPParallelForSimdDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPParallelForSimdDirective), alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd)); @@ -438,8 +430,8 @@ OMPParallelForSimdDirective * OMPParallelForSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = llvm::alignTo(sizeof(OMPParallelForSimdDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPParallelForSimdDirective), alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd)); @@ -449,8 +441,8 @@ OMPParallelForSimdDirective::CreateEmpty(const ASTContext &C, OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) { - unsigned Size = llvm::alignTo(sizeof(OMPParallelSectionsDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPParallelSectionsDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPParallelSectionsDirective *Dir = @@ -464,8 +456,8 @@ OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create( OMPParallelSectionsDirective * OMPParallelSectionsDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { - unsigned Size = llvm::alignTo(sizeof(OMPParallelSectionsDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPParallelSectionsDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPParallelSectionsDirective(NumClauses); @@ -475,8 +467,7 @@ OMPTaskDirective * OMPTaskDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) { - unsigned Size = - llvm::alignTo(sizeof(OMPTaskDirective), llvm::alignOf<OMPClause *>()); + unsigned Size = llvm::alignTo(sizeof(OMPTaskDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPTaskDirective *Dir = @@ -490,8 +481,7 @@ OMPTaskDirective::Create(const ASTContext &C, SourceLocation StartLoc, OMPTaskDirective *OMPTaskDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { - unsigned Size = - llvm::alignTo(sizeof(OMPTaskDirective), llvm::alignOf<OMPClause *>()); + unsigned Size = llvm::alignTo(sizeof(OMPTaskDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPTaskDirective(NumClauses); @@ -544,8 +534,7 @@ OMPTaskgroupDirective *OMPTaskgroupDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt) { - unsigned Size = - llvm::alignTo(sizeof(OMPTaskgroupDirective), llvm::alignOf<Stmt *>()); + unsigned Size = llvm::alignTo(sizeof(OMPTaskgroupDirective), alignof(Stmt *)); void *Mem = C.Allocate(Size + sizeof(Stmt *)); OMPTaskgroupDirective *Dir = new (Mem) OMPTaskgroupDirective(StartLoc, EndLoc); @@ -555,8 +544,7 @@ OMPTaskgroupDirective *OMPTaskgroupDirective::Create(const ASTContext &C, OMPTaskgroupDirective *OMPTaskgroupDirective::CreateEmpty(const ASTContext &C, EmptyShell) { - unsigned Size = - llvm::alignTo(sizeof(OMPTaskgroupDirective), llvm::alignOf<Stmt *>()); + unsigned Size = llvm::alignTo(sizeof(OMPTaskgroupDirective), alignof(Stmt *)); void *Mem = C.Allocate(Size + sizeof(Stmt *)); return new (Mem) OMPTaskgroupDirective(); } @@ -564,8 +552,8 @@ OMPTaskgroupDirective *OMPTaskgroupDirective::CreateEmpty(const ASTContext &C, OMPCancellationPointDirective *OMPCancellationPointDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) { - unsigned Size = llvm::alignTo(sizeof(OMPCancellationPointDirective), - llvm::alignOf<Stmt *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPCancellationPointDirective), alignof(Stmt *)); void *Mem = C.Allocate(Size); OMPCancellationPointDirective *Dir = new (Mem) OMPCancellationPointDirective(StartLoc, EndLoc); @@ -575,8 +563,8 @@ OMPCancellationPointDirective *OMPCancellationPointDirective::Create( OMPCancellationPointDirective * OMPCancellationPointDirective::CreateEmpty(const ASTContext &C, EmptyShell) { - unsigned Size = llvm::alignTo(sizeof(OMPCancellationPointDirective), - llvm::alignOf<Stmt *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPCancellationPointDirective), alignof(Stmt *)); void *Mem = C.Allocate(Size); return new (Mem) OMPCancellationPointDirective(); } @@ -587,7 +575,7 @@ OMPCancelDirective::Create(const ASTContext &C, SourceLocation StartLoc, OpenMPDirectiveKind CancelRegion) { unsigned Size = llvm::alignTo(sizeof(OMPCancelDirective) + sizeof(OMPClause *) * Clauses.size(), - llvm::alignOf<Stmt *>()); + alignof(Stmt *)); void *Mem = C.Allocate(Size); OMPCancelDirective *Dir = new (Mem) OMPCancelDirective(StartLoc, EndLoc, Clauses.size()); @@ -601,7 +589,7 @@ OMPCancelDirective *OMPCancelDirective::CreateEmpty(const ASTContext &C, EmptyShell) { unsigned Size = llvm::alignTo(sizeof(OMPCancelDirective) + sizeof(OMPClause *) * NumClauses, - llvm::alignOf<Stmt *>()); + alignof(Stmt *)); void *Mem = C.Allocate(Size); return new (Mem) OMPCancelDirective(NumClauses); } @@ -611,7 +599,7 @@ OMPFlushDirective *OMPFlushDirective::Create(const ASTContext &C, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses) { unsigned Size = - llvm::alignTo(sizeof(OMPFlushDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPFlushDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size()); OMPFlushDirective *Dir = new (Mem) OMPFlushDirective(StartLoc, EndLoc, Clauses.size()); @@ -623,7 +611,7 @@ OMPFlushDirective *OMPFlushDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPFlushDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPFlushDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses); return new (Mem) OMPFlushDirective(NumClauses); } @@ -634,7 +622,7 @@ OMPOrderedDirective *OMPOrderedDirective::Create(const ASTContext &C, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { unsigned Size = - llvm::alignTo(sizeof(OMPOrderedDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPOrderedDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(Stmt *) + sizeof(OMPClause *) * Clauses.size()); OMPOrderedDirective *Dir = @@ -648,7 +636,7 @@ OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPOrderedDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPOrderedDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(Stmt *) + sizeof(OMPClause *) * NumClauses); return new (Mem) OMPOrderedDirective(NumClauses); @@ -659,7 +647,7 @@ OMPAtomicDirective *OMPAtomicDirective::Create( ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V, Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate) { unsigned Size = - llvm::alignTo(sizeof(OMPAtomicDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPAtomicDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + 5 * sizeof(Stmt *)); OMPAtomicDirective *Dir = @@ -679,7 +667,7 @@ OMPAtomicDirective *OMPAtomicDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPAtomicDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPAtomicDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + 5 * sizeof(Stmt *)); return new (Mem) OMPAtomicDirective(NumClauses); @@ -691,7 +679,7 @@ OMPTargetDirective *OMPTargetDirective::Create(const ASTContext &C, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { unsigned Size = - llvm::alignTo(sizeof(OMPTargetDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPTargetDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPTargetDirective *Dir = @@ -705,7 +693,7 @@ OMPTargetDirective *OMPTargetDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPTargetDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPTargetDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPTargetDirective(NumClauses); @@ -714,8 +702,8 @@ OMPTargetDirective *OMPTargetDirective::CreateEmpty(const ASTContext &C, OMPTargetParallelDirective *OMPTargetParallelDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { - unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTargetParallelDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPTargetParallelDirective *Dir = @@ -728,8 +716,8 @@ OMPTargetParallelDirective *OMPTargetParallelDirective::Create( OMPTargetParallelDirective * OMPTargetParallelDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { - unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTargetParallelDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPTargetParallelDirective(NumClauses); @@ -740,7 +728,7 @@ OMPTargetParallelForDirective *OMPTargetParallelForDirective::Create( unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel) { unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForDirective), - llvm::alignOf<OMPClause *>()); + alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_target_parallel_for)); @@ -780,7 +768,7 @@ OMPTargetParallelForDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForDirective), - llvm::alignOf<OMPClause *>()); + alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_target_parallel_for)); @@ -790,9 +778,9 @@ OMPTargetParallelForDirective::CreateEmpty(const ASTContext &C, OMPTargetDataDirective *OMPTargetDataDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { - void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetDataDirective), - llvm::alignOf<OMPClause *>()) + - sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + void *Mem = C.Allocate( + llvm::alignTo(sizeof(OMPTargetDataDirective), alignof(OMPClause *)) + + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPTargetDataDirective *Dir = new (Mem) OMPTargetDataDirective(StartLoc, EndLoc, Clauses.size()); Dir->setClauses(Clauses); @@ -803,18 +791,18 @@ OMPTargetDataDirective *OMPTargetDataDirective::Create( OMPTargetDataDirective *OMPTargetDataDirective::CreateEmpty(const ASTContext &C, unsigned N, EmptyShell) { - void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetDataDirective), - llvm::alignOf<OMPClause *>()) + - sizeof(OMPClause *) * N + sizeof(Stmt *)); + void *Mem = C.Allocate( + llvm::alignTo(sizeof(OMPTargetDataDirective), alignof(OMPClause *)) + + sizeof(OMPClause *) * N + sizeof(Stmt *)); return new (Mem) OMPTargetDataDirective(N); } OMPTargetEnterDataDirective *OMPTargetEnterDataDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses) { - void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetEnterDataDirective), - llvm::alignOf<OMPClause *>()) + - sizeof(OMPClause *) * Clauses.size()); + void *Mem = C.Allocate( + llvm::alignTo(sizeof(OMPTargetEnterDataDirective), alignof(OMPClause *)) + + sizeof(OMPClause *) * Clauses.size()); OMPTargetEnterDataDirective *Dir = new (Mem) OMPTargetEnterDataDirective(StartLoc, EndLoc, Clauses.size()); Dir->setClauses(Clauses); @@ -824,9 +812,9 @@ OMPTargetEnterDataDirective *OMPTargetEnterDataDirective::Create( OMPTargetEnterDataDirective * OMPTargetEnterDataDirective::CreateEmpty(const ASTContext &C, unsigned N, EmptyShell) { - void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetEnterDataDirective), - llvm::alignOf<OMPClause *>()) + - sizeof(OMPClause *) * N); + void *Mem = C.Allocate( + llvm::alignTo(sizeof(OMPTargetEnterDataDirective), alignof(OMPClause *)) + + sizeof(OMPClause *) * N); return new (Mem) OMPTargetEnterDataDirective(N); } @@ -834,9 +822,9 @@ OMPTargetExitDataDirective * OMPTargetExitDataDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses) { - void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetExitDataDirective), - llvm::alignOf<OMPClause *>()) + - sizeof(OMPClause *) * Clauses.size()); + void *Mem = C.Allocate( + llvm::alignTo(sizeof(OMPTargetExitDataDirective), alignof(OMPClause *)) + + sizeof(OMPClause *) * Clauses.size()); OMPTargetExitDataDirective *Dir = new (Mem) OMPTargetExitDataDirective(StartLoc, EndLoc, Clauses.size()); Dir->setClauses(Clauses); @@ -846,9 +834,9 @@ OMPTargetExitDataDirective::Create(const ASTContext &C, SourceLocation StartLoc, OMPTargetExitDataDirective * OMPTargetExitDataDirective::CreateEmpty(const ASTContext &C, unsigned N, EmptyShell) { - void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetExitDataDirective), - llvm::alignOf<OMPClause *>()) + - sizeof(OMPClause *) * N); + void *Mem = C.Allocate( + llvm::alignTo(sizeof(OMPTargetExitDataDirective), alignof(OMPClause *)) + + sizeof(OMPClause *) * N); return new (Mem) OMPTargetExitDataDirective(N); } @@ -858,7 +846,7 @@ OMPTeamsDirective *OMPTeamsDirective::Create(const ASTContext &C, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { unsigned Size = - llvm::alignTo(sizeof(OMPTeamsDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPTeamsDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPTeamsDirective *Dir = @@ -872,7 +860,7 @@ OMPTeamsDirective *OMPTeamsDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPTeamsDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPTeamsDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPTeamsDirective(NumClauses); @@ -883,7 +871,7 @@ OMPTaskLoopDirective *OMPTaskLoopDirective::Create( unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs) { unsigned Size = - llvm::alignTo(sizeof(OMPTaskLoopDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPTaskLoopDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop)); @@ -922,7 +910,7 @@ OMPTaskLoopDirective *OMPTaskLoopDirective::CreateEmpty(const ASTContext &C, unsigned CollapsedNum, EmptyShell) { unsigned Size = - llvm::alignTo(sizeof(OMPTaskLoopDirective), llvm::alignOf<OMPClause *>()); + llvm::alignTo(sizeof(OMPTaskLoopDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop)); @@ -933,8 +921,8 @@ OMPTaskLoopSimdDirective *OMPTaskLoopSimdDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs) { - unsigned Size = llvm::alignTo(sizeof(OMPTaskLoopSimdDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTaskLoopSimdDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop_simd)); @@ -971,8 +959,8 @@ OMPTaskLoopSimdDirective *OMPTaskLoopSimdDirective::Create( OMPTaskLoopSimdDirective * OMPTaskLoopSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = llvm::alignTo(sizeof(OMPTaskLoopSimdDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTaskLoopSimdDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop_simd)); @@ -983,8 +971,8 @@ OMPDistributeDirective *OMPDistributeDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs) { - unsigned Size = llvm::alignTo(sizeof(OMPDistributeDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPDistributeDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_distribute)); @@ -1021,8 +1009,8 @@ OMPDistributeDirective *OMPDistributeDirective::Create( OMPDistributeDirective * OMPDistributeDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = llvm::alignTo(sizeof(OMPDistributeDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPDistributeDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_distribute)); @@ -1033,8 +1021,8 @@ OMPTargetUpdateDirective * OMPTargetUpdateDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses) { - unsigned Size = llvm::alignTo(sizeof(OMPTargetUpdateDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTargetUpdateDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size()); OMPTargetUpdateDirective *Dir = new (Mem) OMPTargetUpdateDirective(StartLoc, EndLoc, Clauses.size()); @@ -1045,8 +1033,8 @@ OMPTargetUpdateDirective::Create(const ASTContext &C, SourceLocation StartLoc, OMPTargetUpdateDirective * OMPTargetUpdateDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { - unsigned Size = llvm::alignTo(sizeof(OMPTargetUpdateDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTargetUpdateDirective), alignof(OMPClause *)); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses); return new (Mem) OMPTargetUpdateDirective(NumClauses); } @@ -1056,7 +1044,7 @@ OMPDistributeParallelForDirective *OMPDistributeParallelForDirective::Create( unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs) { unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForDirective), - llvm::alignOf<OMPClause *>()); + alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * @@ -1098,7 +1086,7 @@ OMPDistributeParallelForDirective::CreateEmpty(const ASTContext &C, unsigned CollapsedNum, EmptyShell) { unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForDirective), - llvm::alignOf<OMPClause *>()); + alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * @@ -1112,7 +1100,7 @@ OMPDistributeParallelForSimdDirective::Create( unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs) { unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForSimdDirective), - llvm::alignOf<OMPClause *>()); + alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * @@ -1154,7 +1142,7 @@ OMPDistributeParallelForSimdDirective::CreateEmpty(const ASTContext &C, unsigned CollapsedNum, EmptyShell) { unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForSimdDirective), - llvm::alignOf<OMPClause *>()); + alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * @@ -1167,8 +1155,8 @@ OMPDistributeSimdDirective *OMPDistributeSimdDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs) { - unsigned Size = llvm::alignTo(sizeof(OMPDistributeSimdDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPDistributeSimdDirective), alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * @@ -1207,8 +1195,8 @@ OMPDistributeSimdDirective * OMPDistributeSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = llvm::alignTo(sizeof(OMPDistributeSimdDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPDistributeSimdDirective), alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * @@ -1221,7 +1209,7 @@ OMPTargetParallelForSimdDirective *OMPTargetParallelForSimdDirective::Create( unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs) { unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForSimdDirective), - llvm::alignOf<OMPClause *>()); + alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * @@ -1263,10 +1251,411 @@ OMPTargetParallelForSimdDirective::CreateEmpty(const ASTContext &C, unsigned CollapsedNum, EmptyShell) { unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForSimdDirective), - llvm::alignOf<OMPClause *>()); + alignof(OMPClause *)); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_target_parallel_for_simd)); return new (Mem) OMPTargetParallelForSimdDirective(CollapsedNum, NumClauses); } + +OMPTargetSimdDirective * +OMPTargetSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, unsigned CollapsedNum, + ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs) { + unsigned Size = + llvm::alignTo(sizeof(OMPTargetSimdDirective), alignof(OMPClause *)); + void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_target_simd)); + OMPTargetSimdDirective *Dir = new (Mem) + OMPTargetSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPTargetSimdDirective * +OMPTargetSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, + unsigned CollapsedNum, EmptyShell) { + unsigned Size = + llvm::alignTo(sizeof(OMPTargetSimdDirective), alignof(OMPClause *)); + void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_target_simd)); + return new (Mem) OMPTargetSimdDirective(CollapsedNum, NumClauses); +} + +OMPTeamsDistributeDirective *OMPTeamsDistributeDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + unsigned Size = + llvm::alignTo(sizeof(OMPTeamsDistributeDirective), alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_teams_distribute)); + OMPTeamsDistributeDirective *Dir = new (Mem) OMPTeamsDistributeDirective( + StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPTeamsDistributeDirective * +OMPTeamsDistributeDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, EmptyShell) { + unsigned Size = + llvm::alignTo(sizeof(OMPTeamsDistributeDirective), alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_teams_distribute)); + return new (Mem) OMPTeamsDistributeDirective(CollapsedNum, NumClauses); +} + +OMPTeamsDistributeSimdDirective *OMPTeamsDistributeSimdDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + unsigned Size = llvm::alignTo(sizeof(OMPTeamsDistributeSimdDirective), + alignof(OMPClause *)); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_teams_distribute_simd)); + OMPTeamsDistributeSimdDirective *Dir = + new (Mem) OMPTeamsDistributeSimdDirective(StartLoc, EndLoc, CollapsedNum, + Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPTeamsDistributeSimdDirective *OMPTeamsDistributeSimdDirective::CreateEmpty( + const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, + EmptyShell) { + unsigned Size = llvm::alignTo(sizeof(OMPTeamsDistributeSimdDirective), + alignof(OMPClause *)); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_teams_distribute_simd)); + return new (Mem) OMPTeamsDistributeSimdDirective(CollapsedNum, NumClauses); +} + +OMPTeamsDistributeParallelForSimdDirective * +OMPTeamsDistributeParallelForSimdDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForSimdDirective), + alignof(OMPClause *)); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, + OMPD_teams_distribute_parallel_for_simd)); + OMPTeamsDistributeParallelForSimdDirective *Dir = new (Mem) + OMPTeamsDistributeParallelForSimdDirective(StartLoc, EndLoc, CollapsedNum, + Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPTeamsDistributeParallelForSimdDirective * +OMPTeamsDistributeParallelForSimdDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForSimdDirective), + alignof(OMPClause *)); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, + OMPD_teams_distribute_parallel_for_simd)); + return new (Mem) + OMPTeamsDistributeParallelForSimdDirective(CollapsedNum, NumClauses); +} + +OMPTeamsDistributeParallelForDirective * +OMPTeamsDistributeParallelForDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForDirective), + alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_teams_distribute_parallel_for)); + OMPTeamsDistributeParallelForDirective *Dir = new (Mem) + OMPTeamsDistributeParallelForDirective(StartLoc, EndLoc, CollapsedNum, + Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPTeamsDistributeParallelForDirective * +OMPTeamsDistributeParallelForDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForDirective), + alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_teams_distribute_parallel_for)); + return new (Mem) + OMPTeamsDistributeParallelForDirective(CollapsedNum, NumClauses); +} + +OMPTargetTeamsDirective *OMPTargetTeamsDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { + auto Size = + llvm::alignTo(sizeof(OMPTargetTeamsDirective), alignof(OMPClause *)); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + OMPTargetTeamsDirective *Dir = + new (Mem) OMPTargetTeamsDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPTargetTeamsDirective * +OMPTargetTeamsDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, + EmptyShell) { + auto Size = + llvm::alignTo(sizeof(OMPTargetTeamsDirective), alignof(OMPClause *)); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + return new (Mem) OMPTargetTeamsDirective(NumClauses); +} + +OMPTargetTeamsDistributeDirective *OMPTargetTeamsDistributeDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + auto Size = llvm::alignTo(sizeof(OMPTargetTeamsDistributeDirective), + alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_target_teams_distribute)); + OMPTargetTeamsDistributeDirective *Dir = + new (Mem) OMPTargetTeamsDistributeDirective(StartLoc, EndLoc, CollapsedNum, + Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPTargetTeamsDistributeDirective * +OMPTargetTeamsDistributeDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + auto Size = llvm::alignTo(sizeof(OMPTargetTeamsDistributeDirective), + alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_target_teams_distribute)); + return new (Mem) OMPTargetTeamsDistributeDirective(CollapsedNum, NumClauses); +} + +OMPTargetTeamsDistributeParallelForDirective * +OMPTargetTeamsDistributeParallelForDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + auto Size = + llvm::alignTo(sizeof(OMPTargetTeamsDistributeParallelForDirective), + alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, + OMPD_target_teams_distribute_parallel_for)); + OMPTargetTeamsDistributeParallelForDirective *Dir = + new (Mem) OMPTargetTeamsDistributeParallelForDirective( + StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPTargetTeamsDistributeParallelForDirective * +OMPTargetTeamsDistributeParallelForDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + auto Size = + llvm::alignTo(sizeof(OMPTargetTeamsDistributeParallelForDirective), + alignof(OMPClause *)); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, + OMPD_target_teams_distribute_parallel_for)); + return new (Mem) + OMPTargetTeamsDistributeParallelForDirective(CollapsedNum, NumClauses); +} diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 8797a13335c40..a8f493dca07d4 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1198,6 +1198,52 @@ void StmtPrinter::VisitOMPTargetParallelForSimdDirective( PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPTargetSimdDirective(OMPTargetSimdDirective *Node) { + Indent() << "#pragma omp target simd "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTeamsDistributeDirective( + OMPTeamsDistributeDirective *Node) { + Indent() << "#pragma omp teams distribute "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTeamsDistributeSimdDirective( + OMPTeamsDistributeSimdDirective *Node) { + Indent() << "#pragma omp teams distribute simd "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTeamsDistributeParallelForSimdDirective( + OMPTeamsDistributeParallelForSimdDirective *Node) { + Indent() << "#pragma omp teams distribute parallel for simd "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTeamsDistributeParallelForDirective( + OMPTeamsDistributeParallelForDirective *Node) { + Indent() << "#pragma omp teams distribute parallel for "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTargetTeamsDirective(OMPTargetTeamsDirective *Node) { + Indent() << "#pragma omp target teams "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTargetTeamsDistributeDirective( + OMPTargetTeamsDistributeDirective *Node) { + Indent() << "#pragma omp target teams distribute "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTargetTeamsDistributeParallelForDirective( + OMPTargetTeamsDistributeParallelForDirective *Node) { + Indent() << "#pragma omp target teams distribute parallel for "; + PrintOMPExecutableDirective(Node); +} + //===----------------------------------------------------------------------===// // Expr printing methods. //===----------------------------------------------------------------------===// @@ -1676,6 +1722,18 @@ void StmtPrinter::VisitInitListExpr(InitListExpr* Node) { OS << "}"; } +void StmtPrinter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *Node) { + // There's no way to express this expression in any of our supported + // languages, so just emit something terse and (hopefully) clear. + OS << "{"; + PrintExpr(Node->getSubExpr()); + OS << "}"; +} + +void StmtPrinter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *Node) { + OS << "*"; +} + void StmtPrinter::VisitParenListExpr(ParenListExpr* Node) { OS << "("; for (unsigned i = 0, e = Node->getNumExprs(); i != e; ++i) { diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 0a39413853a0c..dd59a9b96c98e 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -93,10 +93,6 @@ void StmtProfiler::VisitCompoundStmt(const CompoundStmt *S) { VisitStmt(S); } -void StmtProfiler::VisitSwitchCase(const SwitchCase *S) { - VisitStmt(S); -} - void StmtProfiler::VisitCaseStmt(const CaseStmt *S) { VisitStmt(S); } @@ -727,6 +723,46 @@ void StmtProfiler::VisitOMPTargetParallelForSimdDirective( VisitOMPLoopDirective(S); } +void StmtProfiler::VisitOMPTargetSimdDirective( + const OMPTargetSimdDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPTeamsDistributeDirective( + const OMPTeamsDistributeDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPTeamsDistributeSimdDirective( + const OMPTeamsDistributeSimdDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPTeamsDistributeParallelForSimdDirective( + const OMPTeamsDistributeParallelForSimdDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPTeamsDistributeParallelForDirective( + const OMPTeamsDistributeParallelForDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPTargetTeamsDirective( + const OMPTargetTeamsDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPTargetTeamsDistributeDirective( + const OMPTargetTeamsDistributeDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPTargetTeamsDistributeParallelForDirective( + const OMPTargetTeamsDistributeParallelForDirective *S) { + VisitOMPLoopDirective(S); +} + void StmtProfiler::VisitExpr(const Expr *S) { VisitStmt(S); } @@ -951,6 +987,14 @@ void StmtProfiler::VisitDesignatedInitUpdateExpr( "initializer"); } +void StmtProfiler::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *S) { + VisitExpr(S); +} + +void StmtProfiler::VisitArrayInitIndexExpr(const ArrayInitIndexExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitNoInitExpr(const NoInitExpr *S) { llvm_unreachable("Unexpected NoInitExpr in syntactic form of initializer"); } @@ -1184,6 +1228,12 @@ void StmtProfiler::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) { if (S->isTypeDependent()) { // Type-dependent operator calls are profiled like their underlying // syntactic operator. + // + // An operator call to operator-> is always implicit, so just skip it. The + // enclosing MemberExpr will profile the actual member access. + if (S->getOperator() == OO_Arrow) + return Visit(S->getArg(0)); + UnaryOperatorKind UnaryOp = UO_Extension; BinaryOperatorKind BinaryOp = BO_Comma; Stmt::StmtClass SC = DecodeOperatorCall(S, UnaryOp, BinaryOp); diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp index b75ede862f7ad..099f939c7a759 100644 --- a/lib/AST/TemplateBase.cpp +++ b/lib/AST/TemplateBase.cpp @@ -243,6 +243,31 @@ Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const { return None; } +QualType TemplateArgument::getNonTypeTemplateArgumentType() const { + switch (getKind()) { + case TemplateArgument::Null: + case TemplateArgument::Type: + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + case TemplateArgument::Pack: + return QualType(); + + case TemplateArgument::Integral: + return getIntegralType(); + + case TemplateArgument::Expression: + return getAsExpr()->getType(); + + case TemplateArgument::Declaration: + return getParamTypeForDecl(); + + case TemplateArgument::NullPtr: + return getNullPtrType(); + } + + llvm_unreachable("Invalid TemplateArgument Kind!"); +} + void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const { ID.AddInteger(getKind()); @@ -530,7 +555,7 @@ const ASTTemplateArgumentListInfo * ASTTemplateArgumentListInfo::Create(ASTContext &C, const TemplateArgumentListInfo &List) { std::size_t size = totalSizeToAlloc<TemplateArgumentLoc>(List.size()); - void *Mem = C.Allocate(size, llvm::alignOf<ASTTemplateArgumentListInfo>()); + void *Mem = C.Allocate(size, alignof(ASTTemplateArgumentListInfo)); return new (Mem) ASTTemplateArgumentListInfo(List); } diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 99b024701aa30..0d0cd2e305be2 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/Type.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" #include "clang/AST/CharUnits.h" @@ -19,13 +20,11 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/PrettyPrinter.h" -#include "clang/AST/Type.h" #include "clang/AST/TypeVisitor.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/Support/raw_ostream.h" #include <algorithm> using namespace clang; @@ -532,6 +531,18 @@ bool Type::isObjCInertUnsafeUnretainedType() const { } } +ObjCTypeParamType::ObjCTypeParamType(const ObjCTypeParamDecl *D, + QualType can, + ArrayRef<ObjCProtocolDecl *> protocols) + : Type(ObjCTypeParam, can, can->isDependentType(), + can->isInstantiationDependentType(), + can->isVariablyModifiedType(), + /*ContainsUnexpandedParameterPack=*/false), + OTPDecl(const_cast<ObjCTypeParamDecl*>(D)) +{ + initialize(protocols); +} + ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base, ArrayRef<QualType> typeArgs, ArrayRef<ObjCProtocolDecl *> protocols, @@ -547,15 +558,9 @@ ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base, ObjCObjectTypeBits.NumTypeArgs = typeArgs.size(); assert(getTypeArgsAsWritten().size() == typeArgs.size() && "bitfield overflow in type argument count"); - ObjCObjectTypeBits.NumProtocols = protocols.size(); - assert(getNumProtocols() == protocols.size() && - "bitfield overflow in protocol count"); if (!typeArgs.empty()) memcpy(getTypeArgStorage(), typeArgs.data(), typeArgs.size() * sizeof(QualType)); - if (!protocols.empty()) - memcpy(getProtocolStorage(), protocols.data(), - protocols.size() * sizeof(ObjCProtocolDecl*)); for (auto typeArg : typeArgs) { if (typeArg->isDependentType()) @@ -566,6 +571,9 @@ ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base, if (typeArg->containsUnexpandedParameterPack()) setContainsUnexpandedParameterPack(); } + // Initialize the protocol qualifiers. The protocol storage is known + // after we set number of type arguments. + initialize(protocols); } bool ObjCObjectType::isSpecialized() const { @@ -883,6 +891,7 @@ public: } TRIVIAL_TYPE_CLASS(Typedef) + TRIVIAL_TYPE_CLASS(ObjCTypeParam) QualType VisitAdjustedType(const AdjustedType *T) { QualType originalType = recurse(T->getOriginalType()); @@ -1048,7 +1057,7 @@ QualType simpleTransform(ASTContext &ctx, QualType type, F &&f) { SplitQualType splitType = type.split(); // Visit the type itself. - SimpleTransformVisitor<F> visitor(ctx, std::move(f)); + SimpleTransformVisitor<F> visitor(ctx, std::forward<F>(f)); QualType result = visitor.Visit(splitType.Ty); if (result.isNull()) return result; @@ -1072,13 +1081,24 @@ QualType QualType::substObjCTypeArgs( // Replace an Objective-C type parameter reference with the corresponding // type argument. - if (const auto *typedefTy = dyn_cast<TypedefType>(splitType.Ty)) { - if (auto *typeParam = dyn_cast<ObjCTypeParamDecl>(typedefTy->getDecl())) { + if (const auto *OTPTy = dyn_cast<ObjCTypeParamType>(splitType.Ty)) { + if (auto *typeParam = dyn_cast<ObjCTypeParamDecl>(OTPTy->getDecl())) { // If we have type arguments, use them. if (!typeArgs.empty()) { - // FIXME: Introduce SubstObjCTypeParamType ? QualType argType = typeArgs[typeParam->getIndex()]; - return ctx.getQualifiedType(argType, splitType.Quals); + if (OTPTy->qual_empty()) + return ctx.getQualifiedType(argType, splitType.Quals); + + // Apply protocol lists if exists. + bool hasError; + SmallVector<ObjCProtocolDecl*, 8> protocolsVec; + protocolsVec.append(OTPTy->qual_begin(), + OTPTy->qual_end()); + ArrayRef<ObjCProtocolDecl *> protocolsToApply = protocolsVec; + QualType resultTy = ctx.applyObjCProtocolQualifiers(argType, + protocolsToApply, hasError, true/*allowOnPointerType*/); + + return ctx.getQualifiedType(resultTy, splitType.Quals); } switch (context) { @@ -2317,6 +2337,15 @@ bool QualType::isCXX11PODType(const ASTContext &Context) const { return false; } +bool Type::isAlignValT() const { + if (auto *ET = getAs<EnumType>()) { + auto *II = ET->getDecl()->getIdentifier(); + if (II && II->isStr("align_val_t") && ET->getDecl()->isInStdNamespace()) + return true; + } + return false; +} + bool Type::isPromotableIntegerType() const { if (const BuiltinType *BT = getAs<BuiltinType>()) switch (BT->getKind()) { @@ -2638,6 +2667,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { case CC_X86VectorCall: return "vectorcall"; case CC_X86_64Win64: return "ms_abi"; case CC_X86_64SysV: return "sysv_abi"; + case CC_X86RegCall : return "regcall"; case CC_AAPCS: return "aapcs"; case CC_AAPCS_VFP: return "aapcs-vfp"; case CC_IntelOclBicc: return "intel_ocl_bicc"; @@ -2688,8 +2718,9 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, QualType *exnSlot = argSlot + NumParams; unsigned I = 0; for (QualType ExceptionType : epi.ExceptionSpec.Exceptions) { - // Note that a dependent exception specification does *not* make - // a type dependent; it's not even part of the C++ type system. + // Note that, before C++17, a dependent exception specification does + // *not* make a type dependent; it's not even part of the C++ type + // system. if (ExceptionType->isInstantiationDependentType()) setInstantiationDependent(); @@ -2728,6 +2759,19 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, slot[0] = epi.ExceptionSpec.SourceDecl; } + // If this is a canonical type, and its exception specification is dependent, + // then it's a dependent type. This only happens in C++17 onwards. + if (isCanonicalUnqualified()) { + if (getExceptionSpecType() == EST_Dynamic || + getExceptionSpecType() == EST_ComputedNoexcept) { + assert(hasDependentExceptionSpec() && "type should not be canonical"); + setDependent(); + } + } else if (getCanonicalTypeInternal()->isDependentType()) { + // Ask our canonical type whether our exception specification was dependent. + setDependent(); + } + if (epi.ExtParameterInfos) { ExtParameterInfo *extParamInfos = const_cast<ExtParameterInfo *>(getExtParameterInfosBuffer()); @@ -2748,6 +2792,15 @@ bool FunctionProtoType::hasDependentExceptionSpec() const { return false; } +bool FunctionProtoType::hasInstantiationDependentExceptionSpec() const { + if (Expr *NE = getNoexceptExpr()) + return NE->isInstantiationDependent(); + for (QualType ET : exceptions()) + if (ET->isInstantiationDependentType()) + return true; + return false; +} + FunctionProtoType::NoexceptResult FunctionProtoType::getNoexceptSpec(const ASTContext &ctx) const { ExceptionSpecificationType est = getExceptionSpecType(); @@ -2772,29 +2825,28 @@ FunctionProtoType::getNoexceptSpec(const ASTContext &ctx) const { return value.getBoolValue() ? NR_Nothrow : NR_Throw; } -bool FunctionProtoType::isNothrow(const ASTContext &Ctx, - bool ResultIfDependent) const { +CanThrowResult FunctionProtoType::canThrow(const ASTContext &Ctx) const { ExceptionSpecificationType EST = getExceptionSpecType(); assert(EST != EST_Unevaluated && EST != EST_Uninstantiated); if (EST == EST_DynamicNone || EST == EST_BasicNoexcept) - return true; + return CT_Cannot; - if (EST == EST_Dynamic && ResultIfDependent) { + if (EST == EST_Dynamic) { // A dynamic exception specification is throwing unless every exception // type is an (unexpanded) pack expansion type. for (unsigned I = 0, N = NumExceptions; I != N; ++I) if (!getExceptionType(I)->getAs<PackExpansionType>()) - return false; - return ResultIfDependent; + return CT_Can; + return CT_Dependent; } if (EST != EST_ComputedNoexcept) - return false; + return CT_Can; NoexceptResult NR = getNoexceptSpec(Ctx); if (NR == NR_Dependent) - return ResultIfDependent; - return NR == NR_Nothrow; + return CT_Dependent; + return NR == NR_Nothrow ? CT_Cannot : CT_Can; } bool FunctionProtoType::isTemplateVariadic() const { @@ -2808,7 +2860,7 @@ bool FunctionProtoType::isTemplateVariadic() const { void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, const QualType *ArgTys, unsigned NumParams, const ExtProtoInfo &epi, - const ASTContext &Context) { + const ASTContext &Context, bool Canonical) { // We have to be careful not to get ambiguous profile encodings. // Note that valid type pointers are never ambiguous with anything else. @@ -2847,7 +2899,7 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, ID.AddPointer(Ex.getAsOpaquePtr()); } else if (epi.ExceptionSpec.Type == EST_ComputedNoexcept && epi.ExceptionSpec.NoexceptExpr) { - epi.ExceptionSpec.NoexceptExpr->Profile(ID, Context, false); + epi.ExceptionSpec.NoexceptExpr->Profile(ID, Context, Canonical); } else if (epi.ExceptionSpec.Type == EST_Uninstantiated || epi.ExceptionSpec.Type == EST_Unevaluated) { ID.AddPointer(epi.ExceptionSpec.SourceDecl->getCanonicalDecl()); @@ -2863,7 +2915,7 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) { Profile(ID, getReturnType(), param_type_begin(), NumParams, getExtProtoInfo(), - Ctx); + Ctx, isCanonicalUnqualified()); } QualType TypedefType::desugar() const { @@ -2992,6 +3044,7 @@ bool AttributedType::isQualifier() const { case AttributedType::attr_fastcall: case AttributedType::attr_stdcall: case AttributedType::attr_thiscall: + case AttributedType::attr_regcall: case AttributedType::attr_pascal: case AttributedType::attr_swiftcall: case AttributedType::attr_vectorcall: @@ -3049,6 +3102,7 @@ bool AttributedType::isCallingConv() const { case attr_fastcall: case attr_stdcall: case attr_thiscall: + case attr_regcall: case attr_swiftcall: case attr_vectorcall: case attr_pascal: @@ -3212,6 +3266,20 @@ void ObjCObjectTypeImpl::Profile(llvm::FoldingSetNodeID &ID) { isKindOfTypeAsWritten()); } +void ObjCTypeParamType::Profile(llvm::FoldingSetNodeID &ID, + const ObjCTypeParamDecl *OTPDecl, + ArrayRef<ObjCProtocolDecl *> protocols) { + ID.AddPointer(OTPDecl); + ID.AddInteger(protocols.size()); + for (auto proto : protocols) + ID.AddPointer(proto); +} + +void ObjCTypeParamType::Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getDecl(), + llvm::makeArrayRef(qual_begin(), getNumProtocols())); +} + namespace { /// \brief The cached properties of a type. @@ -3687,10 +3755,18 @@ bool Type::isObjCARCImplicitlyUnretainedType() const { } bool Type::isObjCNSObjectType() const { - if (const TypedefType *typedefType = dyn_cast<TypedefType>(this)) - return typedefType->getDecl()->hasAttr<ObjCNSObjectAttr>(); - return false; + const Type *cur = this; + while (true) { + if (const TypedefType *typedefType = dyn_cast<TypedefType>(cur)) + return typedefType->getDecl()->hasAttr<ObjCNSObjectAttr>(); + + // Single-step desugar until we run out of sugar. + QualType next = cur->getLocallyUnqualifiedSingleStepDesugaredType(); + if (next.getTypePtr() == cur) return false; + cur = next.getTypePtr(); + } } + bool Type::isObjCIndependentClassType() const { if (const TypedefType *typedefType = dyn_cast<TypedefType>(this)) return typedefType->getDecl()->hasAttr<ObjCIndependentClassAttr>(); diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp index 78947d18f953d..7242858f21e64 100644 --- a/lib/AST/TypeLoc.cpp +++ b/lib/AST/TypeLoc.cpp @@ -16,10 +16,9 @@ #include "clang/AST/Expr.h" #include "clang/AST/TypeLocVisitor.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" using namespace clang; -static const unsigned TypeLocMaxDataAlign = llvm::alignOf<void *>(); +static const unsigned TypeLocMaxDataAlign = alignof(void *); //===----------------------------------------------------------------------===// // TypeLoc Implementation @@ -211,7 +210,7 @@ SourceLocation TypeLoc::getEndLoc() const { switch (Cur.getTypeLocClass()) { default: if (!Last) - Last = Cur; + Last = Cur; return Last.getLocalSourceRange().getEnd(); case Paren: case ConstantArray: @@ -389,6 +388,17 @@ TypeLoc TypeLoc::findExplicitQualifierLoc() const { return TypeLoc(); } +void ObjCTypeParamTypeLoc::initializeLocal(ASTContext &Context, + SourceLocation Loc) { + setNameLoc(Loc); + if (!getNumProtocols()) return; + + setProtocolLAngleLoc(Loc); + setProtocolRAngleLoc(Loc); + for (unsigned i = 0, e = getNumProtocols(); i != e; ++i) + setProtocolLoc(i, Loc); +} + void ObjCObjectTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) { setHasBaseTypeAsWritten(true); diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 065a2db091418..cccc908763212 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -194,6 +194,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::DependentName: case Type::DependentTemplateSpecialization: case Type::ObjCObject: + case Type::ObjCTypeParam: case Type::ObjCInterface: case Type::Atomic: case Type::Pipe: @@ -724,6 +725,9 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, case CC_X86_64SysV: OS << " __attribute__((sysv_abi))"; break; + case CC_X86RegCall: + OS << " __attribute__((regcall))"; + break; case CC_SpirFunction: case CC_OpenCLKernel: // Do nothing. These CCs are not available as attributes. @@ -897,6 +901,10 @@ void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) { } void TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); + if (T->isReadOnly()) + OS << "read_only "; + else + OS << "write_only "; OS << "pipe "; print(T->getElementType(), OS, StringRef()); spaceBeforePlaceHolder(OS); @@ -1338,6 +1346,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, case AttributedType::attr_pascal: OS << "pascal"; break; case AttributedType::attr_ms_abi: OS << "ms_abi"; break; case AttributedType::attr_sysv_abi: OS << "sysv_abi"; break; + case AttributedType::attr_regcall: OS << "regcall"; break; case AttributedType::attr_pcs: case AttributedType::attr_pcs_vfp: { OS << "pcs("; @@ -1368,6 +1377,28 @@ void TypePrinter::printObjCInterfaceBefore(const ObjCInterfaceType *T, void TypePrinter::printObjCInterfaceAfter(const ObjCInterfaceType *T, raw_ostream &OS) { } +void TypePrinter::printObjCTypeParamBefore(const ObjCTypeParamType *T, + raw_ostream &OS) { + OS << T->getDecl()->getName(); + if (!T->qual_empty()) { + bool isFirst = true; + OS << '<'; + for (const auto *I : T->quals()) { + if (isFirst) + isFirst = false; + else + OS << ','; + OS << I->getName(); + } + OS << '>'; + } + + spaceBeforePlaceHolder(OS); +} + +void TypePrinter::printObjCTypeParamAfter(const ObjCTypeParamType *T, + raw_ostream &OS) { } + void TypePrinter::printObjCObjectBefore(const ObjCObjectType *T, raw_ostream &OS) { if (T->qual_empty() && T->isUnspecializedAsWritten() && diff --git a/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp index 640fbf47aeab5..e60ae33f2e5c0 100644 --- a/lib/AST/VTableBuilder.cpp +++ b/lib/AST/VTableBuilder.cpp @@ -777,9 +777,8 @@ public: typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> VBaseOffsetOffsetsMapTy; - - typedef llvm::DenseMap<BaseSubobject, uint64_t> - AddressPointsMapTy; + + typedef VTableLayout::AddressPointsMapTy AddressPointsMapTy; typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy; @@ -817,7 +816,7 @@ private: /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets for /// the most derived class. VBaseOffsetOffsetsMapTy VBaseOffsetOffsets; - + /// Components - The components of the vtable being built. SmallVector<VTableComponent, 64> Components; @@ -982,6 +981,10 @@ private: } public: + /// Component indices of the first component of each of the vtables in the + /// vtable group. + SmallVector<size_t, 4> VTableIndices; + ItaniumVTableBuilder(ItaniumVTableContext &VTables, const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset, @@ -1028,20 +1031,8 @@ public: return MethodVTableIndices.end(); } - /// getNumVTableComponents - Return the number of components in the vtable - /// currently built. - uint64_t getNumVTableComponents() const { - return Components.size(); - } + ArrayRef<VTableComponent> vtable_components() const { return Components; } - const VTableComponent *vtable_component_begin() const { - return Components.begin(); - } - - const VTableComponent *vtable_component_end() const { - return Components.end(); - } - AddressPointsMapTy::const_iterator address_points_begin() const { return AddressPoints.begin(); } @@ -1639,6 +1630,9 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables( bool BaseIsVirtualInLayoutClass, CharUnits OffsetInLayoutClass) { assert(Base.getBase()->isDynamicClass() && "class does not have a vtable!"); + unsigned VTableIndex = Components.size(); + VTableIndices.push_back(VTableIndex); + // Add vcall and vbase offsets for this vtable. VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, LayoutClass, &Overriders, Base, BaseIsVirtualInLayoutClass, @@ -1695,9 +1689,11 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables( // Add all address points. while (true) { - AddressPoints.insert(std::make_pair( - BaseSubobject(RD, OffsetInLayoutClass), - AddressPoint)); + AddressPoints.insert( + std::make_pair(BaseSubobject(RD, OffsetInLayoutClass), + VTableLayout::AddressPointLocation{ + unsigned(VTableIndices.size() - 1), + unsigned(AddressPoint - VTableIndex)})); const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); @@ -1901,7 +1897,8 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex; for (const auto &AP : AddressPoints) { const BaseSubobject &Base = AP.first; - uint64_t Index = AP.second; + uint64_t Index = + VTableIndices[AP.second.VTableIndex] + AP.second.AddressPointIndex; AddressPointsByIndex.insert(std::make_pair(Index, Base)); } @@ -2203,30 +2200,24 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { } } -VTableLayout::VTableLayout(uint64_t NumVTableComponents, - const VTableComponent *VTableComponents, - uint64_t NumVTableThunks, - const VTableThunkTy *VTableThunks, - const AddressPointsMapTy &AddressPoints, - bool IsMicrosoftABI) - : NumVTableComponents(NumVTableComponents), - VTableComponents(new VTableComponent[NumVTableComponents]), - NumVTableThunks(NumVTableThunks), - VTableThunks(new VTableThunkTy[NumVTableThunks]), - AddressPoints(AddressPoints), - IsMicrosoftABI(IsMicrosoftABI) { - std::copy(VTableComponents, VTableComponents+NumVTableComponents, - this->VTableComponents.get()); - std::copy(VTableThunks, VTableThunks+NumVTableThunks, - this->VTableThunks.get()); - std::sort(this->VTableThunks.get(), - this->VTableThunks.get() + NumVTableThunks, +VTableLayout::VTableLayout(ArrayRef<size_t> VTableIndices, + ArrayRef<VTableComponent> VTableComponents, + ArrayRef<VTableThunkTy> VTableThunks, + const AddressPointsMapTy &AddressPoints) + : VTableComponents(VTableComponents), VTableThunks(VTableThunks), + AddressPoints(AddressPoints) { + if (VTableIndices.size() <= 1) + assert(VTableIndices.size() == 1 && VTableIndices[0] == 0); + else + this->VTableIndices = OwningArrayRef<size_t>(VTableIndices); + + std::sort(this->VTableThunks.begin(), this->VTableThunks.end(), [](const VTableLayout::VTableThunkTy &LHS, const VTableLayout::VTableThunkTy &RHS) { - assert((LHS.first != RHS.first || LHS.second == RHS.second) && - "Different thunks should have unique indices!"); - return LHS.first < RHS.first; - }); + assert((LHS.first != RHS.first || LHS.second == RHS.second) && + "Different thunks should have unique indices!"); + return LHS.first < RHS.first; + }); } VTableLayout::~VTableLayout() { } @@ -2234,9 +2225,7 @@ VTableLayout::~VTableLayout() { } ItaniumVTableContext::ItaniumVTableContext(ASTContext &Context) : VTableContextBase(/*MS=*/false) {} -ItaniumVTableContext::~ItaniumVTableContext() { - llvm::DeleteContainerSeconds(VTableLayouts); -} +ItaniumVTableContext::~ItaniumVTableContext() {} uint64_t ItaniumVTableContext::getMethodVTableIndex(GlobalDecl GD) { MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD); @@ -2280,21 +2269,19 @@ ItaniumVTableContext::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, return I->second; } -static VTableLayout *CreateVTableLayout(const ItaniumVTableBuilder &Builder) { +static std::unique_ptr<VTableLayout> +CreateVTableLayout(const ItaniumVTableBuilder &Builder) { SmallVector<VTableLayout::VTableThunkTy, 1> VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end()); - return new VTableLayout(Builder.getNumVTableComponents(), - Builder.vtable_component_begin(), - VTableThunks.size(), - VTableThunks.data(), - Builder.getAddressPoints(), - /*IsMicrosoftABI=*/false); + return llvm::make_unique<VTableLayout>( + Builder.VTableIndices, Builder.vtable_components(), VTableThunks, + Builder.getAddressPoints()); } void ItaniumVTableContext::computeVTableRelatedInformation(const CXXRecordDecl *RD) { - const VTableLayout *&Entry = VTableLayouts[RD]; + std::unique_ptr<const VTableLayout> &Entry = VTableLayouts[RD]; // Check if we've computed this information before. if (Entry) @@ -2330,7 +2317,8 @@ ItaniumVTableContext::computeVTableRelatedInformation(const CXXRecordDecl *RD) { } } -VTableLayout *ItaniumVTableContext::createConstructionVTableLayout( +std::unique_ptr<VTableLayout> +ItaniumVTableContext::createConstructionVTableLayout( const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset, bool MostDerivedClassIsVirtual, const CXXRecordDecl *LayoutClass) { ItaniumVTableBuilder Builder(*this, MostDerivedClass, MostDerivedClassOffset, @@ -2538,12 +2526,12 @@ private: public: VFTableBuilder(MicrosoftVTableContext &VTables, - const CXXRecordDecl *MostDerivedClass, const VPtrInfo *Which) + const CXXRecordDecl *MostDerivedClass, const VPtrInfo &Which) : VTables(VTables), Context(MostDerivedClass->getASTContext()), MostDerivedClass(MostDerivedClass), MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)), - WhichVFPtr(*Which), + WhichVFPtr(Which), Overriders(MostDerivedClass, CharUnits(), MostDerivedClass) { // Provide the RTTI component if RTTIData is enabled. If the vftable would // be available externally, we should not provide the RTTI componenent. It @@ -2570,15 +2558,7 @@ public: MethodVFTableLocations.end()); } - uint64_t getNumVTableComponents() const { return Components.size(); } - - const VTableComponent *vtable_component_begin() const { - return Components.begin(); - } - - const VTableComponent *vtable_component_end() const { - return Components.end(); - } + ArrayRef<VTableComponent> vtable_components() const { return Components; } VTableThunksMapTy::const_iterator vtable_thunks_begin() const { return VTableThunks.begin(); @@ -2931,8 +2911,8 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, // class. const CXXRecordDecl *NextBase = nullptr, *NextLastVBase = LastVBase; CharUnits NextBaseOffset; - if (BaseDepth < WhichVFPtr.PathToBaseWithVPtr.size()) { - NextBase = WhichVFPtr.PathToBaseWithVPtr[BaseDepth]; + if (BaseDepth < WhichVFPtr.PathToIntroducingObject.size()) { + NextBase = WhichVFPtr.PathToIntroducingObject[BaseDepth]; if (isDirectVBase(NextBase, RD)) { NextLastVBase = NextBase; NextBaseOffset = MostDerivedClassLayout.getVBaseClassOffset(NextBase); @@ -3124,7 +3104,7 @@ static void dumpMicrosoftThunkAdjustment(const ThunkInfo &TI, raw_ostream &Out, void VFTableBuilder::dumpLayout(raw_ostream &Out) { Out << "VFTable for "; - PrintBasePath(WhichVFPtr.PathToBaseWithVPtr, Out); + PrintBasePath(WhichVFPtr.PathToIntroducingObject, Out); Out << "'"; MostDerivedClass->printQualifiedName(Out); Out << "' (" << Components.size() @@ -3278,7 +3258,7 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables, // Base case: this subobject has its own vptr. if (ForVBTables ? Layout.hasOwnVBPtr() : Layout.hasOwnVFPtr()) - Paths.push_back(new VPtrInfo(RD)); + Paths.push_back(llvm::make_unique<VPtrInfo>(RD)); // Recursive case: get all the vbtables from our bases and remove anything // that shares a virtual base. @@ -3294,14 +3274,14 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables, const VPtrInfoVector &BasePaths = ForVBTables ? enumerateVBTables(Base) : getVFPtrOffsets(Base); - for (VPtrInfo *BaseInfo : BasePaths) { + for (const std::unique_ptr<VPtrInfo> &BaseInfo : BasePaths) { // Don't include the path if it goes through a virtual base that we've // already included. if (setsIntersect(VBasesSeen, BaseInfo->ContainingVBases)) continue; // Copy the path and adjust it as necessary. - VPtrInfo *P = new VPtrInfo(*BaseInfo); + auto P = llvm::make_unique<VPtrInfo>(*BaseInfo); // We mangle Base into the path if the path would've been ambiguous and it // wasn't already extended with Base. @@ -3311,10 +3291,10 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables, // Keep track of which vtable the derived class is going to extend with // new methods or bases. We append to either the vftable of our primary // base, or the first non-virtual base that has a vbtable. - if (P->ReusingBase == Base && + if (P->ObjectWithVPtr == Base && Base == (ForVBTables ? Layout.getBaseSharingVBPtr() : Layout.getPrimaryBase())) - P->ReusingBase = RD; + P->ObjectWithVPtr = RD; // Keep track of the full adjustment from the MDC to this vtable. The // adjustment is captured by an optional vbase and a non-virtual offset. @@ -3328,7 +3308,7 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables, if (const CXXRecordDecl *VB = P->getVBaseWithVPtr()) P->FullOffsetInMDC += Layout.getVBaseClassOffset(VB); - Paths.push_back(P); + Paths.push_back(std::move(P)); } if (B.isVirtual()) @@ -3347,10 +3327,10 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables, Changed = rebucketPaths(Paths); } -static bool extendPath(VPtrInfo *P) { - if (P->NextBaseToMangle) { - P->MangledPath.push_back(P->NextBaseToMangle); - P->NextBaseToMangle = nullptr;// Prevent the path from being extended twice. +static bool extendPath(VPtrInfo &P) { + if (P.NextBaseToMangle) { + P.MangledPath.push_back(P.NextBaseToMangle); + P.NextBaseToMangle = nullptr;// Prevent the path from being extended twice. return true; } return false; @@ -3363,10 +3343,13 @@ static bool rebucketPaths(VPtrInfoVector &Paths) { // sorted vector to implement a multiset to form the buckets. Note that the // ordering is based on pointers, but it doesn't change our output order. The // current algorithm is designed to match MSVC 2012's names. - VPtrInfoVector PathsSorted(Paths); + llvm::SmallVector<std::reference_wrapper<VPtrInfo>, 2> PathsSorted; + PathsSorted.reserve(Paths.size()); + for (auto& P : Paths) + PathsSorted.push_back(*P); std::sort(PathsSorted.begin(), PathsSorted.end(), - [](const VPtrInfo *LHS, const VPtrInfo *RHS) { - return LHS->MangledPath < RHS->MangledPath; + [](const VPtrInfo &LHS, const VPtrInfo &RHS) { + return LHS.MangledPath < RHS.MangledPath; }); bool Changed = false; for (size_t I = 0, E = PathsSorted.size(); I != E;) { @@ -3374,8 +3357,9 @@ static bool rebucketPaths(VPtrInfoVector &Paths) { size_t BucketStart = I; do { ++I; - } while (I != E && PathsSorted[BucketStart]->MangledPath == - PathsSorted[I]->MangledPath); + } while (I != E && + PathsSorted[BucketStart].get().MangledPath == + PathsSorted[I].get().MangledPath); // If this bucket has multiple paths, extend them all. if (I - BucketStart > 1) { @@ -3387,13 +3371,7 @@ static bool rebucketPaths(VPtrInfoVector &Paths) { return Changed; } -MicrosoftVTableContext::~MicrosoftVTableContext() { - for (auto &P : VFPtrLocations) - llvm::DeleteContainerPointers(*P.second); - llvm::DeleteContainerSeconds(VFPtrLocations); - llvm::DeleteContainerSeconds(VFTableLayouts); - llvm::DeleteContainerSeconds(VBaseInfo); -} +MicrosoftVTableContext::~MicrosoftVTableContext() {} namespace { typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>, @@ -3401,14 +3379,14 @@ typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>, } // This recursive function finds all paths from a subobject centered at -// (RD, Offset) to the subobject located at BaseWithVPtr. +// (RD, Offset) to the subobject located at IntroducingObject. static void findPathsToSubobject(ASTContext &Context, const ASTRecordLayout &MostDerivedLayout, const CXXRecordDecl *RD, CharUnits Offset, - BaseSubobject BaseWithVPtr, + BaseSubobject IntroducingObject, FullPathTy &FullPath, std::list<FullPathTy> &Paths) { - if (BaseSubobject(RD, Offset) == BaseWithVPtr) { + if (BaseSubobject(RD, Offset) == IntroducingObject) { Paths.push_back(FullPath); return; } @@ -3422,7 +3400,7 @@ static void findPathsToSubobject(ASTContext &Context, : Offset + Layout.getBaseClassOffset(Base); FullPath.insert(BaseSubobject(Base, NewOffset)); findPathsToSubobject(Context, MostDerivedLayout, Base, NewOffset, - BaseWithVPtr, FullPath, Paths); + IntroducingObject, FullPath, Paths); FullPath.pop_back(); } } @@ -3477,7 +3455,8 @@ static CharUnits getOffsetOfFullPath(ASTContext &Context, // two paths introduce overrides which the other path doesn't contain, issue a // diagnostic. static const FullPathTy *selectBestPath(ASTContext &Context, - const CXXRecordDecl *RD, VPtrInfo *Info, + const CXXRecordDecl *RD, + const VPtrInfo &Info, std::list<FullPathTy> &FullPaths) { // Handle some easy cases first. if (FullPaths.empty()) @@ -3497,7 +3476,7 @@ static const FullPathTy *selectBestPath(ASTContext &Context, CharUnits BaseOffset = getOffsetOfFullPath(Context, TopLevelRD, SpecificPath); FinalOverriders Overriders(TopLevelRD, CharUnits::Zero(), TopLevelRD); - for (const CXXMethodDecl *MD : Info->BaseWithVPtr->methods()) { + for (const CXXMethodDecl *MD : Info.IntroducingObject->methods()) { if (!MD->isVirtual()) continue; FinalOverriders::OverriderInfo OI = @@ -3552,18 +3531,18 @@ static void computeFullPathsForVFTables(ASTContext &Context, const ASTRecordLayout &MostDerivedLayout = Context.getASTRecordLayout(RD); FullPathTy FullPath; std::list<FullPathTy> FullPaths; - for (VPtrInfo *Info : Paths) { + for (const std::unique_ptr<VPtrInfo>& Info : Paths) { findPathsToSubobject( Context, MostDerivedLayout, RD, CharUnits::Zero(), - BaseSubobject(Info->BaseWithVPtr, Info->FullOffsetInMDC), FullPath, + BaseSubobject(Info->IntroducingObject, Info->FullOffsetInMDC), FullPath, FullPaths); FullPath.clear(); removeRedundantPaths(FullPaths); - Info->PathToBaseWithVPtr.clear(); + Info->PathToIntroducingObject.clear(); if (const FullPathTy *BestPath = - selectBestPath(Context, RD, Info, FullPaths)) + selectBestPath(Context, RD, *Info, FullPaths)) for (const BaseSubobject &BSO : *BestPath) - Info->PathToBaseWithVPtr.push_back(BSO.getBase()); + Info->PathToIntroducingObject.push_back(BSO.getBase()); FullPaths.clear(); } } @@ -3578,22 +3557,24 @@ void MicrosoftVTableContext::computeVTableRelatedInformation( const VTableLayout::AddressPointsMapTy EmptyAddressPointsMap; - VPtrInfoVector *VFPtrs = new VPtrInfoVector(); - computeVTablePaths(/*ForVBTables=*/false, RD, *VFPtrs); - computeFullPathsForVFTables(Context, RD, *VFPtrs); - VFPtrLocations[RD] = VFPtrs; + { + VPtrInfoVector VFPtrs; + computeVTablePaths(/*ForVBTables=*/false, RD, VFPtrs); + computeFullPathsForVFTables(Context, RD, VFPtrs); + VFPtrLocations[RD] = std::move(VFPtrs); + } MethodVFTableLocationsTy NewMethodLocations; - for (const VPtrInfo *VFPtr : *VFPtrs) { - VFTableBuilder Builder(*this, RD, VFPtr); + for (const std::unique_ptr<VPtrInfo> &VFPtr : VFPtrLocations[RD]) { + VFTableBuilder Builder(*this, RD, *VFPtr); VFTableIdTy id(RD, VFPtr->FullOffsetInMDC); assert(VFTableLayouts.count(id) == 0); SmallVector<VTableLayout::VTableThunkTy, 1> VTableThunks( Builder.vtable_thunks_begin(), Builder.vtable_thunks_end()); - VFTableLayouts[id] = new VTableLayout( - Builder.getNumVTableComponents(), Builder.vtable_component_begin(), - VTableThunks.size(), VTableThunks.data(), EmptyAddressPointsMap, true); + VFTableLayouts[id] = llvm::make_unique<VTableLayout>( + ArrayRef<size_t>{0}, Builder.vtable_components(), VTableThunks, + EmptyAddressPointsMap); Thunks.insert(Builder.thunks_begin(), Builder.thunks_end()); for (const auto &Loc : Builder.vtable_locations()) { @@ -3670,17 +3651,18 @@ void MicrosoftVTableContext::dumpMethodLocations( Out.flush(); } -const VirtualBaseInfo *MicrosoftVTableContext::computeVBTableRelatedInformation( +const VirtualBaseInfo &MicrosoftVTableContext::computeVBTableRelatedInformation( const CXXRecordDecl *RD) { VirtualBaseInfo *VBI; { // Get or create a VBI for RD. Don't hold a reference to the DenseMap cell, // as it may be modified and rehashed under us. - VirtualBaseInfo *&Entry = VBaseInfo[RD]; + std::unique_ptr<VirtualBaseInfo> &Entry = VBaseInfo[RD]; if (Entry) - return Entry; - Entry = VBI = new VirtualBaseInfo(); + return *Entry; + Entry = llvm::make_unique<VirtualBaseInfo>(); + VBI = Entry.get(); } computeVTablePaths(/*ForVBTables=*/true, RD, VBI->VBPtrPaths); @@ -3690,10 +3672,10 @@ const VirtualBaseInfo *MicrosoftVTableContext::computeVBTableRelatedInformation( if (const CXXRecordDecl *VBPtrBase = Layout.getBaseSharingVBPtr()) { // If the Derived class shares the vbptr with a non-virtual base, the shared // virtual bases come first so that the layout is the same. - const VirtualBaseInfo *BaseInfo = + const VirtualBaseInfo &BaseInfo = computeVBTableRelatedInformation(VBPtrBase); - VBI->VBTableIndices.insert(BaseInfo->VBTableIndices.begin(), - BaseInfo->VBTableIndices.end()); + VBI->VBTableIndices.insert(BaseInfo.VBTableIndices.begin(), + BaseInfo.VBTableIndices.end()); } // New vbases are added to the end of the vbtable. @@ -3705,19 +3687,19 @@ const VirtualBaseInfo *MicrosoftVTableContext::computeVBTableRelatedInformation( VBI->VBTableIndices[CurVBase] = VBTableIndex++; } - return VBI; + return *VBI; } unsigned MicrosoftVTableContext::getVBTableIndex(const CXXRecordDecl *Derived, const CXXRecordDecl *VBase) { - const VirtualBaseInfo *VBInfo = computeVBTableRelatedInformation(Derived); - assert(VBInfo->VBTableIndices.count(VBase)); - return VBInfo->VBTableIndices.find(VBase)->second; + const VirtualBaseInfo &VBInfo = computeVBTableRelatedInformation(Derived); + assert(VBInfo.VBTableIndices.count(VBase)); + return VBInfo.VBTableIndices.find(VBase)->second; } const VPtrInfoVector & MicrosoftVTableContext::enumerateVBTables(const CXXRecordDecl *RD) { - return computeVBTableRelatedInformation(RD)->VBPtrPaths; + return computeVBTableRelatedInformation(RD).VBPtrPaths; } const VPtrInfoVector & @@ -3725,7 +3707,7 @@ MicrosoftVTableContext::getVFPtrOffsets(const CXXRecordDecl *RD) { computeVTableRelatedInformation(RD); assert(VFPtrLocations.count(RD) && "Couldn't find vfptr locations"); - return *VFPtrLocations[RD]; + return VFPtrLocations[RD]; } const VTableLayout & |