diff options
Diffstat (limited to 'clang/lib/AST')
48 files changed, 2954 insertions, 964 deletions
diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index ef333c771166..a22031142c7c 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -625,6 +625,67 @@ static double GetApproxValue(const llvm::APFloat &F) { return V.convertToDouble(); } +static bool TryPrintAsStringLiteral(raw_ostream &Out, + const PrintingPolicy &Policy, + const ArrayType *ATy, + ArrayRef<APValue> Inits) { + if (Inits.empty()) + return false; + + QualType Ty = ATy->getElementType(); + if (!Ty->isAnyCharacterType()) + return false; + + // Nothing we can do about a sequence that is not null-terminated + if (!Inits.back().getInt().isZero()) + return false; + else + Inits = Inits.drop_back(); + + llvm::SmallString<40> Buf; + Buf.push_back('"'); + + // Better than printing a two-digit sequence of 10 integers. + constexpr size_t MaxN = 36; + StringRef Ellipsis; + if (Inits.size() > MaxN && !Policy.EntireContentsOfLargeArray) { + Ellipsis = "[...]"; + Inits = + Inits.take_front(std::min(MaxN - Ellipsis.size() / 2, Inits.size())); + } + + for (auto &Val : Inits) { + int64_t Char64 = Val.getInt().getExtValue(); + if (!isASCII(Char64)) + return false; // Bye bye, see you in integers. + auto Ch = static_cast<unsigned char>(Char64); + // The diagnostic message is 'quoted' + StringRef Escaped = escapeCStyle<EscapeChar::SingleAndDouble>(Ch); + if (Escaped.empty()) { + if (!isPrintable(Ch)) + return false; + Buf.emplace_back(Ch); + } else { + Buf.append(Escaped); + } + } + + Buf.append(Ellipsis); + Buf.push_back('"'); + + if (Ty->isWideCharType()) + Out << 'L'; + else if (Ty->isChar8Type()) + Out << "u8"; + else if (Ty->isChar16Type()) + Out << 'u'; + else if (Ty->isChar32Type()) + Out << 'U'; + + Out << Buf; + return true; +} + void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, QualType Ty) const { printPretty(Out, Ctx.getPrintingPolicy(), Ty, &Ctx); @@ -700,7 +761,7 @@ void APValue::printPretty(raw_ostream &Out, const PrintingPolicy &Policy, if (!hasLValuePath()) { // No lvalue path: just print the offset. CharUnits O = getLValueOffset(); - CharUnits S = Ctx ? Ctx->getTypeSizeInCharsIfKnown(InnerTy).getValueOr( + CharUnits S = Ctx ? Ctx->getTypeSizeInCharsIfKnown(InnerTy).value_or( CharUnits::Zero()) : CharUnits::Zero(); if (!O.isZero()) { @@ -795,17 +856,23 @@ void APValue::printPretty(raw_ostream &Out, const PrintingPolicy &Policy, } case APValue::Array: { const ArrayType *AT = Ty->castAsArrayTypeUnsafe(); + unsigned N = getArrayInitializedElts(); + if (N != 0 && TryPrintAsStringLiteral(Out, Policy, AT, + {&getArrayInitializedElt(0), N})) + return; QualType ElemTy = AT->getElementType(); Out << '{'; - if (unsigned N = getArrayInitializedElts()) { - getArrayInitializedElt(0).printPretty(Out, Policy, ElemTy, Ctx); - for (unsigned I = 1; I != N; ++I) { + unsigned I = 0; + switch (N) { + case 0: + for (; I != N; ++I) { Out << ", "; - if (I == 10) { - // Avoid printing out the entire contents of large arrays. - Out << "..."; - break; + if (I == 10 && !Policy.EntireContentsOfLargeArray) { + Out << "...}"; + return; } + LLVM_FALLTHROUGH; + default: getArrayInitializedElt(I).printPretty(Out, Policy, ElemTy, Ctx); } } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 5fa2d46de89b..682b71a3d686 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -739,8 +739,8 @@ canonicalizeImmediatelyDeclaredConstraint(const ASTContext &C, Expr *IDC, // template<typename... T> concept C = true; // template<C<int> T> struct S; -> constraint is C<{T, int}> NewConverted.push_back(ConstrainedType); - for (auto &Arg : OldConverted.front().pack_elements().drop_front(1)) - NewConverted.push_back(Arg); + llvm::append_range(NewConverted, + OldConverted.front().pack_elements().drop_front(1)); TemplateArgument NewPack(NewConverted); NewConverted.clear(); @@ -752,8 +752,7 @@ canonicalizeImmediatelyDeclaredConstraint(const ASTContext &C, Expr *IDC, "Unexpected first argument kind for immediately-declared " "constraint"); NewConverted.push_back(ConstrainedType); - for (auto &Arg : OldConverted.drop_front(1)) - NewConverted.push_back(Arg); + llvm::append_range(NewConverted, OldConverted.drop_front(1)); } Expr *NewIDC = ConceptSpecializationExpr::Create( C, CSE->getNamedConcept(), NewConverted, nullptr, @@ -888,7 +887,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( TargetCXXABI::Kind ASTContext::getCXXABIKind() const { auto Kind = getTargetInfo().getCXXABI().getKind(); - return getLangOpts().CXXABI.getValueOr(Kind); + return getLangOpts().CXXABI.value_or(Kind); } CXXABI *ASTContext::createCXXABI(const TargetInfo &T) { @@ -973,7 +972,8 @@ static bool isAddrSpaceMapManglingEnabled(const TargetInfo &TI, ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents, SelectorTable &sels, Builtin::Context &builtins, TranslationUnitKind TUKind) - : ConstantArrayTypes(this_()), FunctionProtoTypes(this_()), + : ConstantArrayTypes(this_(), ConstantArrayTypesLog2InitSize), + FunctionProtoTypes(this_(), FunctionProtoTypesLog2InitSize), TemplateSpecializationTypes(this_()), DependentTemplateSpecializationTypes(this_()), AutoTypes(this_()), SubstTemplateTemplateParmPacks(this_()), @@ -1707,8 +1707,17 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const { case BuiltinType::BFloat16: return Target->getBFloat16Format(); case BuiltinType::Float16: - case BuiltinType::Half: return Target->getHalfFormat(); + case BuiltinType::Half: + // For HLSL, when the native half type is disabled, half will be treat as + // float. + if (getLangOpts().HLSL) + if (getLangOpts().NativeHalfType) + return Target->getHalfFormat(); + else + return Target->getFloatFormat(); + else + return Target->getHalfFormat(); case BuiltinType::Float: return Target->getFloatFormat(); case BuiltinType::Double: return Target->getDoubleFormat(); case BuiltinType::Ibm128: @@ -1981,8 +1990,11 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { case Type::Vector: { const auto *VT = cast<VectorType>(T); TypeInfo EltInfo = getTypeInfo(VT->getElementType()); - Width = EltInfo.Width * VT->getNumElements(); - Align = Width; + Width = VT->isExtVectorBoolType() ? VT->getNumElements() + : EltInfo.Width * VT->getNumElements(); + // Enforce at least byte alignment. + Align = std::max<unsigned>(8, Width); + // If the alignment is not a power of 2, round up to the next power of 2. // This happens for non-power-of-2 length vectors. if (Align & (Align-1)) { @@ -2115,8 +2127,10 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Align = Target->getLongFractAlign(); break; case BuiltinType::BFloat16: - Width = Target->getBFloat16Width(); - Align = Target->getBFloat16Align(); + if (Target->hasBFloat16Type()) { + Width = Target->getBFloat16Width(); + Align = Target->getBFloat16Align(); + } break; case BuiltinType::Float16: case BuiltinType::Half: @@ -2376,6 +2390,10 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { return getTypeInfo( cast<AttributedType>(T)->getEquivalentType().getTypePtr()); + case Type::BTFTagAttributed: + return getTypeInfo( + cast<BTFTagAttributedType>(T)->getWrappedType().getTypePtr()); + case Type::Atomic: { // Start with the base type information. TypeInfo Info = getTypeInfo(cast<AtomicType>(T)->getValueType()); @@ -2593,8 +2611,7 @@ void ASTContext::DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, if (const ObjCInterfaceDecl *SuperClass = OI->getSuperClass()) DeepCollectObjCIvars(SuperClass, false, Ivars); if (!leafClass) { - for (const auto *I : OI->ivars()) - Ivars.push_back(I); + llvm::append_range(Ivars, OI->ivars()); } else { auto *IDecl = const_cast<ObjCInterfaceDecl *>(OI); for (const ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv; @@ -2676,7 +2693,11 @@ getSubobjectSizeInBits(const FieldDecl *Field, const ASTContext &Context) { if (!RD->isUnion()) return structHasUniqueObjectRepresentations(Context, RD); } - if (!Field->getType()->isReferenceType() && + + // A _BitInt type may not be unique if it has padding bits + // but if it is a bitfield the padding bits are not used. + bool IsBitIntType = Field->getType()->isBitIntType(); + if (!Field->getType()->isReferenceType() && !IsBitIntType && !Context.hasUniqueObjectRepresentations(Field->getType())) return llvm::None; @@ -2684,9 +2705,17 @@ getSubobjectSizeInBits(const FieldDecl *Field, const ASTContext &Context) { Context.toBits(Context.getTypeSizeInChars(Field->getType())); if (Field->isBitField()) { int64_t BitfieldSize = Field->getBitWidthValue(Context); - if (BitfieldSize > FieldSizeInBits) + if (IsBitIntType) { + if ((unsigned)BitfieldSize > + cast<BitIntType>(Field->getType())->getNumBits()) + return llvm::None; + } else if (BitfieldSize > FieldSizeInBits) { return llvm::None; + } FieldSizeInBits = BitfieldSize; + } else if (IsBitIntType && + !Context.hasUniqueObjectRepresentations(Field->getType())) { + return llvm::None; } return FieldSizeInBits; } @@ -2784,8 +2813,13 @@ bool ASTContext::hasUniqueObjectRepresentations(QualType Ty) const { return false; // All integrals and enums are unique. - if (Ty->isIntegralOrEnumerationType()) + if (Ty->isIntegralOrEnumerationType()) { + // Except _BitInt types that have padding bits. + if (const auto *BIT = dyn_cast<BitIntType>(Ty)) + return getTypeSize(BIT) == BIT->getNumBits(); + return true; + } // All other pointers are unique. if (Ty->isPointerType()) @@ -2808,8 +2842,7 @@ bool ASTContext::hasUniqueObjectRepresentations(QualType Ty) const { Optional<int64_t> StructSize = structHasUniqueObjectRepresentations(*this, Record); - return StructSize && - StructSize.getValue() == static_cast<int64_t>(getTypeSize(Ty)); + return StructSize && *StructSize == static_cast<int64_t>(getTypeSize(Ty)); } // FIXME: More cases to handle here (list by rsmith): @@ -4233,6 +4266,13 @@ static bool isCanonicalResultType(QualType T) { QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, const FunctionType::ExtInfo &Info) const { + // FIXME: This assertion cannot be enabled (yet) because the ObjC rewriter + // functionality creates a function without a prototype regardless of + // language mode (so it makes them even in C++). Once the rewriter has been + // fixed, this assertion can be enabled again. + //assert(!LangOpts.requiresStrictPrototypes() && + // "strict prototypes are disabled"); + // Unique functions, to guarantee there is only one function of a particular // structure. llvm::FoldingSetNodeID ID; @@ -4436,8 +4476,7 @@ QualType ASTContext::getFunctionTypeInternal( QualType, SourceLocation, FunctionType::FunctionTypeExtraBitfields, FunctionType::ExceptionType, Expr *, FunctionDecl *, FunctionProtoType::ExtParameterInfo, Qualifiers>( - NumArgs, EPI.Variadic, - FunctionProtoType::hasExtraBitfields(EPI.ExceptionSpec.Type), + NumArgs, EPI.Variadic, EPI.requiresFunctionProtoTypeExtraBitfields(), ESH.NumExceptionType, ESH.NumExprPtr, ESH.NumFunctionDeclPtr, EPI.ExtParameterInfos ? NumArgs : 0, EPI.TypeQuals.hasNonFastQualifiers() ? 1 : 0); @@ -4682,6 +4721,26 @@ QualType ASTContext::getAttributedType(attr::Kind attrKind, return QualType(type, 0); } +QualType ASTContext::getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr, + QualType Wrapped) { + llvm::FoldingSetNodeID ID; + BTFTagAttributedType::Profile(ID, Wrapped, BTFAttr); + + void *InsertPos = nullptr; + BTFTagAttributedType *Ty = + BTFTagAttributedTypes.FindNodeOrInsertPos(ID, InsertPos); + if (Ty) + return QualType(Ty, 0); + + QualType Canon = getCanonicalType(Wrapped); + Ty = new (*this, TypeAlignment) BTFTagAttributedType(Canon, Wrapped, BTFAttr); + + Types.push_back(Ty); + BTFTagAttributedTypes.InsertNode(Ty, InsertPos); + + return QualType(Ty, 0); +} + /// Retrieve a substitution-result type. QualType ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm, @@ -4826,11 +4885,10 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, "No dependent template names here!"); // Look through qualified template names. if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) - Template = TemplateName(QTN->getTemplateDecl()); + Template = QTN->getUnderlyingTemplate(); bool IsTypeAlias = - Template.getAsTemplateDecl() && - isa<TypeAliasTemplateDecl>(Template.getAsTemplateDecl()); + isa_and_nonnull<TypeAliasTemplateDecl>(Template.getAsTemplateDecl()); QualType CanonType; if (!Underlying.isNull()) CanonType = getCanonicalType(Underlying); @@ -4882,7 +4940,7 @@ QualType ASTContext::getCanonicalTemplateSpecializationType( // Look through qualified template names. if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) - Template = TemplateName(QTN->getTemplateDecl()); + Template = TemplateName(QTN->getUnderlyingTemplate()); // Build the canonical template specialization type. TemplateName CanonTemplate = getCanonicalTemplateName(Template); @@ -6099,6 +6157,9 @@ ASTContext::getNameForTemplate(TemplateName Name, return DeclarationNameInfo(subst->getParameterPack()->getDeclName(), NameLoc); } + case TemplateName::UsingTemplate: + return DeclarationNameInfo(Name.getAsUsingShadowDecl()->getDeclName(), + NameLoc); } llvm_unreachable("bad template name kind!"); @@ -6107,6 +6168,7 @@ ASTContext::getNameForTemplate(TemplateName Name, TemplateName ASTContext::getCanonicalTemplateName(const TemplateName &Name) const { switch (Name.getKind()) { + case TemplateName::UsingTemplate: case TemplateName::QualifiedTemplate: case TemplateName::Template: { TemplateDecl *Template = Name.getAsTemplateDecl(); @@ -6797,41 +6859,6 @@ static FloatingRank getFloatingRank(QualType T) { } } -/// getFloatingTypeOfSizeWithinDomain - Returns a real floating -/// point or a complex type (based on typeDomain/typeSize). -/// 'typeDomain' is a real floating point or complex type. -/// 'typeSize' is a real floating point or complex type. -QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size, - QualType Domain) const { - FloatingRank EltRank = getFloatingRank(Size); - if (Domain->isComplexType()) { - switch (EltRank) { - case BFloat16Rank: llvm_unreachable("Complex bfloat16 is not supported"); - case Float16Rank: - case HalfRank: llvm_unreachable("Complex half is not supported"); - case Ibm128Rank: return getComplexType(Ibm128Ty); - case FloatRank: return getComplexType(FloatTy); - case DoubleRank: return getComplexType(DoubleTy); - case LongDoubleRank: return getComplexType(LongDoubleTy); - case Float128Rank: return getComplexType(Float128Ty); - } - } - - assert(Domain->isRealFloatingType() && "Unknown domain!"); - switch (EltRank) { - case Float16Rank: return HalfTy; - case BFloat16Rank: return BFloat16Ty; - case HalfRank: return HalfTy; - case FloatRank: return FloatTy; - case DoubleRank: return DoubleTy; - case LongDoubleRank: return LongDoubleTy; - case Float128Rank: return Float128Ty; - case Ibm128Rank: - return Ibm128Ty; - } - llvm_unreachable("getFloatingRank(): illegal value for rank"); -} - /// getFloatingTypeOrder - Compare the rank of the two specified floating /// point types, ignoring the domain of the type (i.e. 'double' == /// '_Complex double'). If LHS > RHS, return 1. If LHS == RHS, return 0. If @@ -8547,21 +8574,18 @@ static TypedefDecl *CreateVoidPtrBuiltinVaListDecl(const ASTContext *Context) { static TypedefDecl * CreateAArch64ABIBuiltinVaListDecl(const ASTContext *Context) { + // struct __va_list RecordDecl *VaListTagDecl = Context->buildImplicitRecord("__va_list"); - // namespace std { struct __va_list { - // Note that we create the namespace even in C. This is intentional so that - // the type is consistent between C and C++, which is important in cases where - // the types need to match between translation units (e.g. with - // -fsanitize=cfi-icall). Ideally we wouldn't have created this namespace at - // all, but it's now part of the ABI (e.g. in mangled names), so we can't - // change it. - auto *NS = NamespaceDecl::Create( - const_cast<ASTContext &>(*Context), Context->getTranslationUnitDecl(), - /*Inline*/ false, SourceLocation(), SourceLocation(), - &Context->Idents.get("std"), - /*PrevDecl*/ nullptr); - NS->setImplicit(); - VaListTagDecl->setDeclContext(NS); + if (Context->getLangOpts().CPlusPlus) { + // namespace std { struct __va_list { + auto *NS = NamespaceDecl::Create( + const_cast<ASTContext &>(*Context), Context->getTranslationUnitDecl(), + /*Inline*/ false, SourceLocation(), SourceLocation(), + &Context->Idents.get("std"), + /*PrevDecl*/ nullptr); + NS->setImplicit(); + VaListTagDecl->setDeclContext(NS); + } VaListTagDecl->startDefinition(); @@ -8979,10 +9003,9 @@ TemplateName ASTContext::getAssumedTemplateName(DeclarationName Name) const { /// Retrieve the template name that represents a qualified /// template name such as \c std::vector. -TemplateName -ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS, - bool TemplateKeyword, - TemplateDecl *Template) const { +TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS, + bool TemplateKeyword, + TemplateName Template) const { assert(NNS && "Missing nested-name-specifier in qualified template name"); // FIXME: Canonicalization? @@ -10297,7 +10320,16 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, if (RHS->isObjCIdType() && LHS->isBlockPointerType()) return RHS; } - + // Allow __auto_type to match anything; it merges to the type with more + // information. + if (const auto *AT = LHS->getAs<AutoType>()) { + if (!AT->isDeduced() && AT->isGNUAutoType()) + return RHS; + } + if (const auto *AT = RHS->getAs<AutoType>()) { + if (!AT->isDeduced() && AT->isGNUAutoType()) + return LHS; + } return {}; } @@ -11234,7 +11266,7 @@ QualType ASTContext::GetBuiltinType(unsigned Id, // We really shouldn't be making a no-proto type here. - if (ArgTypes.empty() && Variadic && !getLangOpts().CPlusPlus) + if (ArgTypes.empty() && Variadic && !getLangOpts().requiresStrictPrototypes()) return getFunctionNoProtoType(ResType, EI); FunctionProtoType::ExtProtoInfo EPI; @@ -11331,7 +11363,7 @@ static GVALinkage adjustGVALinkageForAttributes(const ASTContext &Context, // name between the host and device compilation which is the same for the // same compilation unit whereas different among different compilation // units. - if (Context.shouldExternalizeStaticVar(D)) + if (Context.shouldExternalize(D)) return GVA_StrongExternal; } return L; @@ -11686,9 +11718,11 @@ MangleContext *ASTContext::createDeviceMangleContext(const TargetInfo &T) { if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) return RD->getDeviceLambdaManglingNumber(); return llvm::None; - }); + }, + /*IsAux=*/true); case TargetCXXABI::Microsoft: - return MicrosoftMangleContext::create(*this, getDiagnostics()); + return MicrosoftMangleContext::create(*this, getDiagnostics(), + /*IsAux=*/true); } llvm_unreachable("Unsupported ABI"); } @@ -11732,6 +11766,8 @@ QualType ASTContext::getRealTypeForBitwidth(unsigned DestWidth, FloatModeKind Ty = getTargetInfo().getRealTypeByWidth(DestWidth, ExplicitType); switch (Ty) { + case FloatModeKind::Half: + return HalfTy; case FloatModeKind::Float: return FloatTy; case FloatModeKind::Double: @@ -11754,9 +11790,19 @@ void ASTContext::setManglingNumber(const NamedDecl *ND, unsigned Number) { MangleNumbers[ND] = Number; } -unsigned ASTContext::getManglingNumber(const NamedDecl *ND) const { +unsigned ASTContext::getManglingNumber(const NamedDecl *ND, + bool ForAuxTarget) const { auto I = MangleNumbers.find(ND); - return I != MangleNumbers.end() ? I->second : 1; + unsigned Res = I != MangleNumbers.end() ? I->second : 1; + // CUDA/HIP host compilation encodes host and device mangling numbers + // as lower and upper half of 32 bit integer. + if (LangOpts.CUDA && !LangOpts.CUDAIsDevice) { + Res = ForAuxTarget ? Res >> 16 : Res & 0xFFFF; + } else { + assert(!ForAuxTarget && "Only CUDA/HIP host compilation supports mangling " + "number for aux target"); + } + return Res > 1 ? Res : 1; } void ASTContext::setStaticLocalNumber(const VarDecl *VD, unsigned Number) { @@ -11855,7 +11901,7 @@ ASTContext::getPredefinedStringLiteralFromCache(StringRef Key) const { StringLiteral *&Result = StringLiteralCache[Key]; if (!Result) Result = StringLiteral::Create( - *this, Key, StringLiteral::Ascii, + *this, Key, StringLiteral::Ordinary, /*Pascal*/ false, getStringLiteralArrayType(CharTy, Key.size()), SourceLocation()); return Result; @@ -11878,6 +11924,23 @@ ASTContext::getMSGuidDecl(MSGuidDecl::Parts Parts) const { return New; } +UnnamedGlobalConstantDecl * +ASTContext::getUnnamedGlobalConstantDecl(QualType Ty, + const APValue &APVal) const { + llvm::FoldingSetNodeID ID; + UnnamedGlobalConstantDecl::Profile(ID, Ty, APVal); + + void *InsertPos; + if (UnnamedGlobalConstantDecl *Existing = + UnnamedGlobalConstantDecls.FindNodeOrInsertPos(ID, InsertPos)) + return Existing; + + UnnamedGlobalConstantDecl *New = + UnnamedGlobalConstantDecl::Create(*this, Ty, APVal); + UnnamedGlobalConstantDecls.InsertNode(New, InsertPos); + return New; +} + TemplateParamObjectDecl * ASTContext::getTemplateParamObjectDecl(QualType T, const APValue &V) const { assert(T->isRecordType() && "template param object of unexpected type"); @@ -11959,8 +12022,13 @@ uint64_t ASTContext::getTargetNullPointerValue(QualType QT) const { } unsigned ASTContext::getTargetAddressSpace(QualType T) const { - return T->isFunctionType() ? getTargetInfo().getProgramAddressSpace() - : getTargetAddressSpace(T.getQualifiers()); + // Return the address space for the type. If the type is a + // function type without an address space qualifier, the + // program address space is used. Otherwise, the target picks + // the best address space based on the type information + return T->isFunctionType() && !T.hasAddressSpace() + ? getTargetInfo().getProgramAddressSpace() + : getTargetAddressSpace(T.getQualifiers()); } unsigned ASTContext::getTargetAddressSpace(Qualifiers Q) const { @@ -12258,7 +12326,7 @@ operator<<(const StreamingDiagnostic &DB, return DB << "a prior #pragma section"; } -bool ASTContext::mayExternalizeStaticVar(const Decl *D) const { +bool ASTContext::mayExternalize(const Decl *D) const { bool IsStaticVar = isa<VarDecl>(D) && cast<VarDecl>(D)->getStorageClass() == SC_Static; bool IsExplicitDeviceVar = (D->hasAttr<CUDADeviceAttr>() && @@ -12266,14 +12334,18 @@ bool ASTContext::mayExternalizeStaticVar(const Decl *D) const { (D->hasAttr<CUDAConstantAttr>() && !D->getAttr<CUDAConstantAttr>()->isImplicit()); // CUDA/HIP: static managed variables need to be externalized since it is - // a declaration in IR, therefore cannot have internal linkage. - return IsStaticVar && - (D->hasAttr<HIPManagedAttr>() || IsExplicitDeviceVar); + // a declaration in IR, therefore cannot have internal linkage. Kernels in + // anonymous name space needs to be externalized to avoid duplicate symbols. + return (IsStaticVar && + (D->hasAttr<HIPManagedAttr>() || IsExplicitDeviceVar)) || + (D->hasAttr<CUDAGlobalAttr>() && + basicGVALinkageForFunction(*this, cast<FunctionDecl>(D)) == + GVA_Internal); } -bool ASTContext::shouldExternalizeStaticVar(const Decl *D) const { - return mayExternalizeStaticVar(D) && - (D->hasAttr<HIPManagedAttr>() || +bool ASTContext::shouldExternalize(const Decl *D) const { + return mayExternalize(D) && + (D->hasAttr<HIPManagedAttr>() || D->hasAttr<CUDAGlobalAttr>() || CUDADeviceVarODRUsedByHost.count(cast<VarDecl>(D))); } diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp index 724ede272fbf..28269ec219e4 100644 --- a/clang/lib/AST/ASTDiagnostic.cpp +++ b/clang/lib/AST/ASTDiagnostic.cpp @@ -270,9 +270,9 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, std::string S = Ty.getAsString(Context.getPrintingPolicy()); std::string CanS = CanTy.getAsString(Context.getPrintingPolicy()); - for (unsigned I = 0, E = QualTypeVals.size(); I != E; ++I) { + for (const intptr_t &QualTypeVal : QualTypeVals) { QualType CompareTy = - QualType::getFromOpaquePtr(reinterpret_cast<void*>(QualTypeVals[I])); + QualType::getFromOpaquePtr(reinterpret_cast<void *>(QualTypeVal)); if (CompareTy.isNull()) continue; if (CompareTy == Ty) @@ -302,11 +302,11 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, // Check to see if we already desugared this type in this // diagnostic. If so, don't do it again. bool Repeated = false; - for (unsigned i = 0, e = PrevArgs.size(); i != e; ++i) { + for (const auto &PrevArg : PrevArgs) { // TODO: Handle ak_declcontext case. - if (PrevArgs[i].first == DiagnosticsEngine::ak_qualtype) { - void *Ptr = (void*)PrevArgs[i].second; - QualType PrevTy(QualType::getFromOpaquePtr(Ptr)); + if (PrevArg.first == DiagnosticsEngine::ak_qualtype) { + QualType PrevTy( + QualType::getFromOpaquePtr(reinterpret_cast<void *>(PrevArg.second))); if (PrevTy == Ty) { Repeated = true; break; @@ -372,7 +372,7 @@ void clang::FormatASTNodeDiagnosticArgument( default: llvm_unreachable("unknown ArgumentKind"); case DiagnosticsEngine::ak_addrspace: { assert(Modifier.empty() && Argument.empty() && - "Invalid modifier for Qualfiers argument"); + "Invalid modifier for Qualifiers argument"); auto S = Qualifiers::getAddrSpaceAsString(static_cast<LangAS>(Val)); if (S.empty()) { @@ -387,7 +387,7 @@ void clang::FormatASTNodeDiagnosticArgument( } case DiagnosticsEngine::ak_qual: { assert(Modifier.empty() && Argument.empty() && - "Invalid modifier for Qualfiers argument"); + "Invalid modifier for Qualifiers argument"); Qualifiers Q(Qualifiers::fromOpaqueValue(Val)); auto S = Q.getAsString(); @@ -1874,7 +1874,7 @@ class TemplateDiff { // FIXME: Diffing the APValue would be neat. // FIXME: Suppress this and use the full name of the declaration if the // parameter is a pointer or reference. - TPO->printAsInit(OS); + TPO->printAsInit(OS, Policy); return; } VD->printName(OS); diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 457465e87d93..e9730112eaa3 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -84,7 +84,7 @@ namespace clang { using ExpectedSLoc = llvm::Expected<SourceLocation>; using ExpectedName = llvm::Expected<DeclarationName>; - std::string ImportError::toString() const { + std::string ASTImportError::toString() const { // FIXME: Improve error texts. switch (Error) { case NameConflict: @@ -98,15 +98,13 @@ namespace clang { return "Invalid error code."; } - void ImportError::log(raw_ostream &OS) const { - OS << toString(); - } + void ASTImportError::log(raw_ostream &OS) const { OS << toString(); } - std::error_code ImportError::convertToErrorCode() const { + std::error_code ASTImportError::convertToErrorCode() const { llvm_unreachable("Function not implemented."); } - char ImportError::ID; + char ASTImportError::ID; template <class T> SmallVector<Decl *, 2> @@ -138,6 +136,46 @@ namespace clang { To->setIsUsed(); } + /// How to handle import errors that occur when import of a child declaration + /// of a DeclContext fails. + class ChildErrorHandlingStrategy { + /// This context is imported (in the 'from' domain). + /// It is nullptr if a non-DeclContext is imported. + const DeclContext *const FromDC; + /// Ignore import errors of the children. + /// If true, the context can be imported successfully if a child + /// of it failed to import. Otherwise the import errors of the child nodes + /// are accumulated (joined) into the import error object of the parent. + /// (Import of a parent can fail in other ways.) + bool const IgnoreChildErrors; + + public: + ChildErrorHandlingStrategy(const DeclContext *FromDC) + : FromDC(FromDC), IgnoreChildErrors(!isa<TagDecl>(FromDC)) {} + ChildErrorHandlingStrategy(const Decl *FromD) + : FromDC(dyn_cast<DeclContext>(FromD)), + IgnoreChildErrors(!isa<TagDecl>(FromD)) {} + + /// Process the import result of a child (of the current declaration). + /// \param ResultErr The import error that can be used as result of + /// importing the parent. This may be changed by the function. + /// \param ChildErr Result of importing a child. Can be success or error. + void handleChildImportResult(Error &ResultErr, Error &&ChildErr) { + if (ChildErr && !IgnoreChildErrors) + ResultErr = joinErrors(std::move(ResultErr), std::move(ChildErr)); + else + consumeError(std::move(ChildErr)); + } + + /// Determine if import failure of a child does not cause import failure of + /// its parent. + bool ignoreChildErrorOnParent(Decl *FromChildD) const { + if (!IgnoreChildErrors || !FromDC) + return false; + return FromDC->containsDecl(FromChildD); + } + }; + class ASTNodeImporter : public TypeVisitor<ASTNodeImporter, ExpectedType>, public DeclVisitor<ASTNodeImporter, ExpectedDecl>, public StmtVisitor<ASTNodeImporter, ExpectedStmt> { @@ -245,6 +283,7 @@ namespace clang { ToD = CreateFun(std::forward<Args>(args)...); // Keep track of imported Decls. Importer.RegisterImportedDecl(FromD, ToD); + Importer.SharedState->markAsNewDecl(ToD); InitializeImportedDecl(FromD, ToD); return false; // A new Decl is created. } @@ -507,6 +546,7 @@ namespace clang { ExpectedDecl VisitUsingDecl(UsingDecl *D); ExpectedDecl VisitUsingShadowDecl(UsingShadowDecl *D); ExpectedDecl VisitUsingDirectiveDecl(UsingDirectiveDecl *D); + ExpectedDecl VisitUsingPackDecl(UsingPackDecl *D); ExpectedDecl ImportUsingShadowDecls(BaseUsingDecl *D, BaseUsingDecl *ToSI); ExpectedDecl VisitUsingEnumDecl(UsingEnumDecl *D); ExpectedDecl VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); @@ -1025,7 +1065,7 @@ using namespace clang; ExpectedType ASTNodeImporter::VisitType(const Type *T) { Importer.FromDiag(SourceLocation(), diag::err_unsupported_ast_node) << T->getTypeClassName(); - return make_error<ImportError>(ImportError::UnsupportedConstruct); + return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct); } ExpectedType ASTNodeImporter::VisitAtomicType(const AtomicType *T){ @@ -1676,7 +1716,7 @@ Error ASTNodeImporter::ImportDeclParts( if (RT && RT->getDecl() == D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); - return make_error<ImportError>(ImportError::UnsupportedConstruct); + return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct); } } } @@ -1809,7 +1849,7 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { // because there is an ODR error with two typedefs. As another example, // the client may allow EnumConstantDecls with same names but with // different values in two distinct translation units. - bool AccumulateChildErrors = isa<TagDecl>(FromDC); + ChildErrorHandlingStrategy HandleChildErrors(FromDC); Error ChildErrors = Error::success(); for (auto *From : FromDC->decls()) { @@ -1849,20 +1889,14 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { if (FromRecordDecl->isCompleteDefinition() && !ToRecordDecl->isCompleteDefinition()) { Error Err = ImportDefinition(FromRecordDecl, ToRecordDecl); - - if (Err && AccumulateChildErrors) - ChildErrors = joinErrors(std::move(ChildErrors), std::move(Err)); - else - consumeError(std::move(Err)); + HandleChildErrors.handleChildImportResult(ChildErrors, + std::move(Err)); } } } } else { - if (AccumulateChildErrors) - ChildErrors = - joinErrors(std::move(ChildErrors), ImportedOrErr.takeError()); - else - consumeError(ImportedOrErr.takeError()); + HandleChildErrors.handleChildImportResult(ChildErrors, + ImportedOrErr.takeError()); } } @@ -2012,6 +2046,14 @@ Error ASTNodeImporter::ImportDefinition( } To->startDefinition(); + // Set the definition to complete even if it is really not complete during + // import. Some AST constructs (expressions) require the record layout + // to be calculated (see 'clang::computeDependence') at the time they are + // constructed. Import of such AST node is possible during import of the + // same record, there is no way to have a completely defined record (all + // fields imported) at that time without multiple AST import passes. + if (!Importer.isMinimalImport()) + To->setCompleteDefinition(true); // Complete the definition even if error is returned. // The RecordDecl may be already part of the AST so it is better to // have it in complete state even if something is wrong with it. @@ -2076,9 +2118,10 @@ Error ASTNodeImporter::ImportDefinition( ToCXX->setBases(Bases.data(), Bases.size()); } - if (shouldForceImportDeclContext(Kind)) + if (shouldForceImportDeclContext(Kind)) { if (Error Err = ImportDeclContext(From, /*ForceImport=*/true)) return Err; + } return Error::success(); } @@ -2196,13 +2239,13 @@ bool ASTNodeImporter::IsStructuralMatch(Decl *From, Decl *To, bool Complain) { ExpectedDecl ASTNodeImporter::VisitDecl(Decl *D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); - return make_error<ImportError>(ImportError::UnsupportedConstruct); + return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct); } ExpectedDecl ASTNodeImporter::VisitImportDecl(ImportDecl *D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); - return make_error<ImportError>(ImportError::UnsupportedConstruct); + return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct); } ExpectedDecl ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) { @@ -2865,7 +2908,7 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { return TInfoOrErr.takeError(); if (GetImportedOrCreateSpecialDecl( D2CXX, CXXRecordDecl::CreateLambda, D, Importer.getToContext(), - DC, *TInfoOrErr, Loc, DCXX->isDependentLambda(), + DC, *TInfoOrErr, Loc, DCXX->getLambdaDependencyKind(), DCXX->isGenericLambda(), DCXX->getLambdaCaptureDefault())) return D2CXX; ExpectedDecl CDeclOrErr = import(DCXX->getLambdaContextDecl()); @@ -3182,23 +3225,32 @@ static bool isAncestorDeclContextOf(const DeclContext *DC, const Decl *D) { return false; } +static bool hasTypeDeclaredInsideFunction(QualType T, const FunctionDecl *FD) { + if (T.isNull()) + return false; + if (const auto *RecordT = T->getAs<RecordType>()) { + const RecordDecl *RD = RecordT->getDecl(); + assert(RD); + if (isAncestorDeclContextOf(FD, RD)) { + assert(RD->getLexicalDeclContext() == RD->getDeclContext()); + return true; + } + if (const auto *RDTempl = dyn_cast<ClassTemplateSpecializationDecl>(RD)) + return llvm::count_if(RDTempl->getTemplateArgs().asArray(), + [FD](const TemplateArgument &Arg) { + return hasTypeDeclaredInsideFunction( + Arg.getAsType(), FD); + }); + } + return false; +} + bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) { QualType FromTy = D->getType(); const auto *FromFPT = FromTy->getAs<FunctionProtoType>(); assert(FromFPT && "Must be called on FunctionProtoType"); - if (const AutoType *AutoT = - FromFPT->getReturnType()->getContainedAutoType()) { - QualType DeducedT = AutoT->getDeducedType(); - if (const auto *RecordT = - !DeducedT.isNull() ? DeducedT->getAs<RecordType>() : nullptr) { - const RecordDecl *RD = RecordT->getDecl(); - assert(RD); - if (isAncestorDeclContextOf(D, RD)) { - assert(RD->getLexicalDeclContext() == RD->getDeclContext()); - return true; - } - } - } + if (const AutoType *AutoT = FromFPT->getReturnType()->getContainedAutoType()) + return hasTypeDeclaredInsideFunction(AutoT->getDeducedType(), D); if (const auto *TypedefT = FromFPT->getReturnType()->getAs<TypedefType>()) { const TypedefNameDecl *TD = TypedefT->getDecl(); assert(TD); @@ -3637,19 +3689,19 @@ ExpectedDecl ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { // initializer of a FieldDecl might not had been instantiated in the // "To" context. However, the "From" context might instantiated that, // thus we have to merge that. + // Note: `hasInClassInitializer()` is not the same as non-null + // `getInClassInitializer()` value. if (Expr *FromInitializer = D->getInClassInitializer()) { - // We don't have yet the initializer set. - if (FoundField->hasInClassInitializer() && - !FoundField->getInClassInitializer()) { - if (ExpectedExpr ToInitializerOrErr = import(FromInitializer)) + if (ExpectedExpr ToInitializerOrErr = import(FromInitializer)) { + // Import of the FromInitializer may result in the setting of + // InClassInitializer. If not, set it here. + assert(FoundField->hasInClassInitializer() && + "Field should have an in-class initializer if it has an " + "expression for it."); + if (!FoundField->getInClassInitializer()) FoundField->setInClassInitializer(*ToInitializerOrErr); - else { - // We can't return error here, - // since we already mapped D as imported. - // FIXME: warning message? - consumeError(ToInitializerOrErr.takeError()); - return FoundField; - } + } else { + return ToInitializerOrErr.takeError(); } } return FoundField; @@ -3661,7 +3713,7 @@ ExpectedDecl ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) << FoundField->getType(); - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } } @@ -3734,7 +3786,7 @@ ExpectedDecl ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) << FoundField->getType(); - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } } @@ -3925,7 +3977,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { Importer.ToDiag(FoundIvar->getLocation(), diag::note_odr_value_here) << FoundIvar->getType(); - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } } @@ -4233,7 +4285,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } // Check the number of parameters. @@ -4245,7 +4297,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } // Check parameter types. @@ -4261,7 +4313,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { Importer.ToDiag((*FoundP)->getLocation(), diag::note_odr_value_here) << (*FoundP)->getType(); - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } } @@ -4274,7 +4326,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } // FIXME: Any other bits we need to merge? @@ -4788,6 +4840,35 @@ ExpectedDecl ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { return ToUsingDir; } +ExpectedDecl ASTNodeImporter::VisitUsingPackDecl(UsingPackDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD = nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); + if (ToD) + return ToD; + + auto ToInstantiatedFromUsingOrErr = + Importer.Import(D->getInstantiatedFromUsingDecl()); + if (!ToInstantiatedFromUsingOrErr) + return ToInstantiatedFromUsingOrErr.takeError(); + SmallVector<NamedDecl *, 4> Expansions(D->expansions().size()); + if (Error Err = ImportArrayChecked(D->expansions(), Expansions.begin())) + return std::move(Err); + + UsingPackDecl *ToUsingPack; + if (GetImportedOrCreateDecl(ToUsingPack, D, Importer.getToContext(), DC, + cast<NamedDecl>(*ToInstantiatedFromUsingOrErr), + Expansions)) + return ToUsingPack; + + addDeclToContexts(D, ToUsingPack); + + return ToUsingPack; +} + ExpectedDecl ASTNodeImporter::VisitUnresolvedUsingValueDecl( UnresolvedUsingValueDecl *D) { DeclContext *DC, *LexicalDC; @@ -5172,7 +5253,7 @@ ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { Importer.FromDiag(D->getLocation(), diag::note_odr_objc_missing_superclass); - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } } @@ -5211,7 +5292,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { Importer.ToDiag(FoundProp->getLocation(), diag::note_odr_value_here) << FoundProp->getType(); - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } // FIXME: Check property attributes, getters, setters, etc.? @@ -5316,7 +5397,7 @@ ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { << D->getPropertyDecl()->getDeclName() << (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic); - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } // For @synthesize, check that we have the same @@ -5331,7 +5412,7 @@ ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { diag::note_odr_objc_synthesize_ivar_here) << D->getPropertyIvarDecl()->getDeclName(); - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } // Merge the existing implementation with the new implementation. @@ -5661,7 +5742,7 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( } } else { // ODR violation. // FIXME HandleNameConflict - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } } @@ -5944,9 +6025,10 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( return TInfoOrErr.takeError(); TemplateArgumentListInfo ToTAInfo; - if (Error Err = ImportTemplateArgumentListInfo( - D->getTemplateArgsInfo(), ToTAInfo)) - return std::move(Err); + if (const ASTTemplateArgumentListInfo *Args = D->getTemplateArgsInfo()) { + if (Error Err = ImportTemplateArgumentListInfo(*Args, ToTAInfo)) + return std::move(Err); + } using PartVarSpecDecl = VarTemplatePartialSpecializationDecl; // Create a new specialization. @@ -6138,13 +6220,13 @@ ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { ExpectedStmt ASTNodeImporter::VisitStmt(Stmt *S) { Importer.FromDiag(S->getBeginLoc(), diag::err_unsupported_ast_node) << S->getStmtClassName(); - return make_error<ImportError>(ImportError::UnsupportedConstruct); + return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct); } ExpectedStmt ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { if (Importer.returnWithErrorInTest()) - return make_error<ImportError>(ImportError::UnsupportedConstruct); + return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct); SmallVector<IdentifierInfo *, 4> Names; for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) { IdentifierInfo *ToII = Importer.Import(S->getOutputIdentifier(I)); @@ -6257,9 +6339,10 @@ ExpectedStmt ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) { if (!ToRBracLocOrErr) return ToRBracLocOrErr.takeError(); - return CompoundStmt::Create( - Importer.getToContext(), ToStmts, - *ToLBracLocOrErr, *ToRBracLocOrErr); + FPOptionsOverride FPO = + S->hasStoredFPFeatures() ? S->getStoredFPFeatures() : FPOptionsOverride(); + return CompoundStmt::Create(Importer.getToContext(), ToStmts, FPO, + *ToLBracLocOrErr, *ToRBracLocOrErr); } ExpectedStmt ASTNodeImporter::VisitCaseStmt(CaseStmt *S) { @@ -6651,11 +6734,12 @@ ExpectedStmt ASTNodeImporter::VisitObjCAutoreleasePoolStmt( ExpectedStmt ASTNodeImporter::VisitExpr(Expr *E) { Importer.FromDiag(E->getBeginLoc(), diag::err_unsupported_ast_node) << E->getStmtClassName(); - return make_error<ImportError>(ImportError::UnsupportedConstruct); + return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct); } ExpectedStmt ASTNodeImporter::VisitSourceLocExpr(SourceLocExpr *E) { Error Err = Error::success(); + auto ToType = importChecked(Err, E->getType()); auto BLoc = importChecked(Err, E->getBeginLoc()); auto RParenLoc = importChecked(Err, E->getEndLoc()); if (Err) @@ -6665,8 +6749,8 @@ ExpectedStmt ASTNodeImporter::VisitSourceLocExpr(SourceLocExpr *E) { return ParentContextOrErr.takeError(); return new (Importer.getToContext()) - SourceLocExpr(Importer.getToContext(), E->getIdentKind(), BLoc, RParenLoc, - *ParentContextOrErr); + SourceLocExpr(Importer.getToContext(), E->getIdentKind(), ToType, BLoc, + RParenLoc, *ParentContextOrErr); } ExpectedStmt ASTNodeImporter::VisitVAArgExpr(VAArgExpr *E) { @@ -7312,7 +7396,7 @@ ExpectedStmt ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { } default: llvm_unreachable("Cast expression of unsupported type!"); - return make_error<ImportError>(ImportError::UnsupportedConstruct); + return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct); } } @@ -8118,8 +8202,23 @@ ExpectedStmt ASTNodeImporter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) { if (!UsedContextOrErr) return UsedContextOrErr.takeError(); - return CXXDefaultInitExpr::Create( - Importer.getToContext(), *ToBeginLocOrErr, *ToFieldOrErr, *UsedContextOrErr); + FieldDecl *ToField = *ToFieldOrErr; + assert(ToField->hasInClassInitializer() && + "Field should have in-class initializer if there is a default init " + "expression that uses it."); + if (!ToField->getInClassInitializer()) { + // The in-class initializer may be not yet set in "To" AST even if the + // field is already there. This must be set here to make construction of + // CXXDefaultInitExpr work. + auto ToInClassInitializerOrErr = + import(E->getField()->getInClassInitializer()); + if (!ToInClassInitializerOrErr) + return ToInClassInitializerOrErr.takeError(); + ToField->setInClassInitializer(*ToInClassInitializerOrErr); + } + + return CXXDefaultInitExpr::Create(Importer.getToContext(), *ToBeginLocOrErr, + ToField, *UsedContextOrErr); } ExpectedStmt ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { @@ -8158,7 +8257,7 @@ ExpectedStmt ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { ToOperatorLoc, ToRParenLoc, ToAngleBrackets); } else { llvm_unreachable("Unknown cast type"); - return make_error<ImportError>(); + return make_error<ASTImportError>(); } } @@ -8353,7 +8452,7 @@ ASTImporter::Import(ExprWithCleanups::CleanupObject From) { // FIXME: Handle BlockDecl when we implement importing BlockExpr in // ASTNodeImporter. - return make_error<ImportError>(ImportError::UnsupportedConstruct); + return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct); } ExpectedTypePtr ASTImporter::Import(const Type *FromT) { @@ -8558,6 +8657,13 @@ Expected<Attr *> ASTImporter::Import(const Attr *FromAttr) { break; } + case attr::EnableIf: { + const auto *From = cast<EnableIfAttr>(FromAttr); + AI.importAttr(From, AI.importArg(From->getCond()).value(), + From->getMessage()); + break; + } + case attr::AssertCapability: { const auto *From = cast<AssertCapabilityAttr>(FromAttr); AI.importAttr(From, @@ -8697,7 +8803,7 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) { // Check whether there was a previous failed import. // If yes return the existing error. if (auto Error = getImportDeclErrorIfAny(FromD)) - return make_error<ImportError>(*Error); + return make_error<ASTImportError>(*Error); // Check whether we've already imported this declaration. Decl *ToD = GetAlreadyImportedOrNull(FromD); @@ -8705,7 +8811,7 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) { // Already imported (possibly from another TU) and with an error. if (auto Error = SharedState->getImportDeclErrorIfAny(ToD)) { setImportDeclError(FromD, *Error); - return make_error<ImportError>(*Error); + return make_error<ASTImportError>(*Error); } // If FromD has some updated flags after last import, apply it. @@ -8757,9 +8863,9 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) { // Error encountered for the first time. // After takeError the error is not usable any more in ToDOrErr. // Get a copy of the error object (any more simple solution for this?). - ImportError ErrOut; + ASTImportError ErrOut; handleAllErrors(ToDOrErr.takeError(), - [&ErrOut](const ImportError &E) { ErrOut = E; }); + [&ErrOut](const ASTImportError &E) { ErrOut = E; }); setImportDeclError(FromD, ErrOut); // Set the error for the mapped to Decl, which is in the "to" context. if (Pos != ImportedDecls.end()) @@ -8767,8 +8873,20 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) { // Set the error for all nodes which have been created before we // recognized the error. - for (const auto &Path : SavedImportPaths[FromD]) + for (const auto &Path : SavedImportPaths[FromD]) { + // The import path contains import-dependency nodes first. + // Save the node that was imported as dependency of the current node. + Decl *PrevFromDi = FromD; for (Decl *FromDi : Path) { + // Begin and end of the path equals 'FromD', skip it. + if (FromDi == FromD) + continue; + // We should not set import error on a node and all following nodes in + // the path if child import errors are ignored. + if (ChildErrorHandlingStrategy(FromDi).ignoreChildErrorOnParent( + PrevFromDi)) + break; + PrevFromDi = FromDi; setImportDeclError(FromDi, ErrOut); //FIXME Should we remove these Decls from ImportedDecls? // Set the error for the mapped to Decl, which is in the "to" context. @@ -8778,10 +8896,11 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) { // FIXME Should we remove these Decls from the LookupTable, // and from ImportedFromDecls? } + } SavedImportPaths.erase(FromD); // Do not return ToDOrErr, error was taken out of it. - return make_error<ImportError>(ErrOut); + return make_error<ASTImportError>(ErrOut); } ToD = *ToDOrErr; @@ -8793,7 +8912,7 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) { if (!ToD) { auto Err = getImportDeclErrorIfAny(FromD); assert(Err); - return make_error<ImportError>(*Err); + return make_error<ASTImportError>(*Err); } // We could import from the current TU without error. But previously we @@ -8801,7 +8920,7 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) { // ASTImporter object) and with an error. if (auto Error = SharedState->getImportDeclErrorIfAny(ToD)) { setImportDeclError(FromD, *Error); - return make_error<ImportError>(*Error); + return make_error<ASTImportError>(*Error); } // Make sure that ImportImpl registered the imported decl. @@ -9106,13 +9225,11 @@ Expected<TemplateName> ASTImporter::Import(TemplateName From) { auto QualifierOrErr = Import(QTN->getQualifier()); if (!QualifierOrErr) return QualifierOrErr.takeError(); - - if (ExpectedDecl ToTemplateOrErr = Import(From.getAsTemplateDecl())) - return ToContext.getQualifiedTemplateName( - *QualifierOrErr, QTN->hasTemplateKeyword(), - cast<TemplateDecl>(*ToTemplateOrErr)); - else - return ToTemplateOrErr.takeError(); + auto TNOrErr = Import(QTN->getUnderlyingTemplate()); + if (!TNOrErr) + return TNOrErr.takeError(); + return ToContext.getQualifiedTemplateName( + *QualifierOrErr, QTN->hasTemplateKeyword(), *TNOrErr); } case TemplateName::DependentTemplate: { @@ -9161,6 +9278,12 @@ Expected<TemplateName> ASTImporter::Import(TemplateName From) { return ToContext.getSubstTemplateTemplateParmPack( cast<TemplateTemplateParmDecl>(*ParamOrErr), *ArgPackOrErr); } + case TemplateName::UsingTemplate: { + auto UsingOrError = Import(From.getAsUsingShadowDecl()); + if (!UsingOrError) + return UsingOrError.takeError(); + return TemplateName(cast<UsingShadowDecl>(*UsingOrError)); + } } llvm_unreachable("Invalid template name kind"); @@ -9210,13 +9333,13 @@ Expected<FileID> ASTImporter::Import(FileID FromID, bool IsBuiltin) { ExpectedSLoc ToExLocS = Import(FromEx.getExpansionLocStart()); if (!ToExLocS) return ToExLocS.takeError(); - unsigned TokenLen = FromSM.getFileIDSize(FromID); + unsigned ExLength = FromSM.getFileIDSize(FromID); SourceLocation MLoc; if (FromEx.isMacroArgExpansion()) { - MLoc = ToSM.createMacroArgExpansionLoc(*ToSpLoc, *ToExLocS, TokenLen); + MLoc = ToSM.createMacroArgExpansionLoc(*ToSpLoc, *ToExLocS, ExLength); } else { if (ExpectedSLoc ToExLocE = Import(FromEx.getExpansionLocEnd())) - MLoc = ToSM.createExpansionLoc(*ToSpLoc, *ToExLocS, *ToExLocE, TokenLen, + MLoc = ToSM.createExpansionLoc(*ToSpLoc, *ToExLocS, *ToExLocE, ExLength, FromEx.isExpansionTokenRange()); else return ToExLocE.takeError(); @@ -9262,7 +9385,7 @@ Expected<FileID> ASTImporter::Import(FileID FromID, bool IsBuiltin) { Cache->getBufferOrNone(FromContext.getDiagnostics(), FromSM.getFileManager(), SourceLocation{}); if (!FromBuf) - return llvm::make_error<ImportError>(ImportError::Unknown); + return llvm::make_error<ASTImportError>(ASTImportError::Unknown); std::unique_ptr<llvm::MemoryBuffer> ToBuf = llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(), @@ -9338,7 +9461,7 @@ Expected<CXXCtorInitializer *> ASTImporter::Import(CXXCtorInitializer *From) { *ToExprOrErr, *RParenLocOrErr); } else { // FIXME: assert? - return make_error<ImportError>(); + return make_error<ASTImportError>(); } } @@ -9667,7 +9790,7 @@ Expected<DeclarationName> ASTImporter::HandleNameConflict(DeclarationName Name, unsigned NumDecls) { if (ODRHandling == ODRHandlingType::Conservative) // Report error at any name conflict. - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); else // Allow to create the new Decl with the same name. return Name; @@ -9727,16 +9850,16 @@ Decl *ASTImporter::MapImported(Decl *From, Decl *To) { return To; } -llvm::Optional<ImportError> +llvm::Optional<ASTImportError> ASTImporter::getImportDeclErrorIfAny(Decl *FromD) const { auto Pos = ImportDeclErrors.find(FromD); if (Pos != ImportDeclErrors.end()) return Pos->second; else - return Optional<ImportError>(); + return Optional<ASTImportError>(); } -void ASTImporter::setImportDeclError(Decl *From, ImportError Error) { +void ASTImporter::setImportDeclError(Decl *From, ASTImportError Error) { auto InsertRes = ImportDeclErrors.insert({From, Error}); (void)InsertRes; // Either we set the error for the first time, or we already had set one and diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index 0813a5204a5e..d80fc3ce7292 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -517,6 +517,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, case TemplateName::Template: case TemplateName::QualifiedTemplate: case TemplateName::SubstTemplateTemplateParm: + case TemplateName::UsingTemplate: // It is sufficient to check value of getAsTemplateDecl. break; @@ -932,6 +933,13 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; break; + case Type::BTFTagAttributed: + if (!IsStructurallyEquivalent( + Context, cast<BTFTagAttributedType>(T1)->getWrappedType(), + cast<BTFTagAttributedType>(T2)->getWrappedType())) + return false; + break; + case Type::Paren: if (!IsStructurallyEquivalent(Context, cast<ParenType>(T1)->getInnerType(), cast<ParenType>(T2)->getInnerType())) @@ -1228,16 +1236,17 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, !IsStructurallyEquivalent(Context, Int1->getNumBitsExpr(), Int2->getNumBitsExpr())) return false; + break; } } // end switch return true; } -/// Determine structural equivalence of two fields. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - FieldDecl *Field1, FieldDecl *Field2) { - const auto *Owner2 = cast<RecordDecl>(Field2->getDeclContext()); + FieldDecl *Field1, FieldDecl *Field2, + QualType Owner2Type) { + const auto *Owner2 = cast<Decl>(Field2->getDeclContext()); // For anonymous structs/unions, match up the anonymous struct/union type // declarations directly, so that we don't go off searching for anonymous @@ -1257,7 +1266,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Context.Diag2( Owner2->getLocation(), Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent)) - << Context.ToCtx.getTypeDeclType(Owner2); + << Owner2Type; Context.Diag2(Field2->getLocation(), diag::note_odr_field_name) << Field2->getDeclName(); Context.Diag1(Field1->getLocation(), diag::note_odr_field_name) @@ -1272,7 +1281,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Context.Diag2( Owner2->getLocation(), Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent)) - << Context.ToCtx.getTypeDeclType(Owner2); + << Owner2Type; Context.Diag2(Field2->getLocation(), diag::note_odr_field) << Field2->getDeclName() << Field2->getType(); Context.Diag1(Field1->getLocation(), diag::note_odr_field) @@ -1288,6 +1297,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return true; } +/// Determine structural equivalence of two fields. +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + FieldDecl *Field1, FieldDecl *Field2) { + const auto *Owner2 = cast<RecordDecl>(Field2->getDeclContext()); + return IsStructurallyEquivalent(Context, Field1, Field2, + Context.ToCtx.getTypeDeclType(Owner2)); +} + /// Determine structural equivalence of two methods. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, CXXMethodDecl *Method1, @@ -1602,6 +1619,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, } // Check the fields for consistency. + QualType D2Type = Context.ToCtx.getTypeDeclType(D2); RecordDecl::field_iterator Field2 = D2->field_begin(), Field2End = D2->field_end(); for (RecordDecl::field_iterator Field1 = D1->field_begin(), @@ -1620,7 +1638,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; } - if (!IsStructurallyEquivalent(Context, *Field1, *Field2)) + if (!IsStructurallyEquivalent(Context, *Field1, *Field2, D2Type)) return false; } @@ -1926,6 +1944,126 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return true; } +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + ObjCIvarDecl *D1, ObjCIvarDecl *D2, + QualType Owner2Type) { + if (D1->getAccessControl() != D2->getAccessControl()) + return false; + + return IsStructurallyEquivalent(Context, cast<FieldDecl>(D1), + cast<FieldDecl>(D2), Owner2Type); +} + +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + ObjCIvarDecl *D1, ObjCIvarDecl *D2) { + QualType Owner2Type = + Context.ToCtx.getObjCInterfaceType(D2->getContainingInterface()); + return IsStructurallyEquivalent(Context, D1, D2, Owner2Type); +} + +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + ObjCMethodDecl *Method1, + ObjCMethodDecl *Method2) { + bool PropertiesEqual = + Method1->isInstanceMethod() == Method2->isInstanceMethod() && + Method1->isVariadic() == Method2->isVariadic() && + Method1->isDirectMethod() == Method2->isDirectMethod(); + if (!PropertiesEqual) + return false; + + // Compare selector slot names. + Selector Selector1 = Method1->getSelector(), + Selector2 = Method2->getSelector(); + unsigned NumArgs = Selector1.getNumArgs(); + if (NumArgs != Selector2.getNumArgs()) + return false; + // Compare all selector slots. For selectors with arguments it means all arg + // slots. And if there are no arguments, compare the first-and-only slot. + unsigned SlotsToCheck = NumArgs > 0 ? NumArgs : 1; + for (unsigned I = 0; I < SlotsToCheck; ++I) { + if (!IsStructurallyEquivalent(Selector1.getIdentifierInfoForSlot(I), + Selector2.getIdentifierInfoForSlot(I))) + return false; + } + + // Compare types. + if (!IsStructurallyEquivalent(Context, Method1->getReturnType(), + Method2->getReturnType())) + return false; + assert( + Method1->param_size() == Method2->param_size() && + "Same number of arguments should be already enforced in Selector checks"); + for (ObjCMethodDecl::param_type_iterator + ParamT1 = Method1->param_type_begin(), + ParamT1End = Method1->param_type_end(), + ParamT2 = Method2->param_type_begin(), + ParamT2End = Method2->param_type_end(); + (ParamT1 != ParamT1End) && (ParamT2 != ParamT2End); + ++ParamT1, ++ParamT2) { + if (!IsStructurallyEquivalent(Context, *ParamT1, *ParamT2)) + return false; + } + + return true; +} + +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + ObjCCategoryDecl *D1, + ObjCCategoryDecl *D2) { + if (!IsStructurallyEquivalent(D1->getIdentifier(), D2->getIdentifier())) + return false; + + if (!IsStructurallyEquivalent(D1->getClassInterface()->getIdentifier(), + D2->getClassInterface()->getIdentifier())) + return false; + + // Compare protocols. + ObjCCategoryDecl::protocol_iterator Protocol2 = D2->protocol_begin(), + Protocol2End = D2->protocol_end(); + for (ObjCCategoryDecl::protocol_iterator Protocol1 = D1->protocol_begin(), + Protocol1End = D1->protocol_end(); + Protocol1 != Protocol1End; ++Protocol1, ++Protocol2) { + if (Protocol2 == Protocol2End) + return false; + if (!IsStructurallyEquivalent((*Protocol1)->getIdentifier(), + (*Protocol2)->getIdentifier())) + return false; + } + if (Protocol2 != Protocol2End) + return false; + + // Compare ivars. + QualType D2Type = Context.ToCtx.getObjCInterfaceType(D2->getClassInterface()); + ObjCCategoryDecl::ivar_iterator Ivar2 = D2->ivar_begin(), + Ivar2End = D2->ivar_end(); + for (ObjCCategoryDecl::ivar_iterator Ivar1 = D1->ivar_begin(), + Ivar1End = D1->ivar_end(); + Ivar1 != Ivar1End; ++Ivar1, ++Ivar2) { + if (Ivar2 == Ivar2End) + return false; + if (!IsStructurallyEquivalent(Context, *Ivar1, *Ivar2, D2Type)) + return false; + } + if (Ivar2 != Ivar2End) + return false; + + // Compare methods. + ObjCCategoryDecl::method_iterator Method2 = D2->meth_begin(), + Method2End = D2->meth_end(); + for (ObjCCategoryDecl::method_iterator Method1 = D1->meth_begin(), + Method1End = D1->meth_end(); + Method1 != Method1End; ++Method1, ++Method2) { + if (Method2 == Method2End) + return false; + if (!IsStructurallyEquivalent(Context, *Method1, *Method2)) + return false; + } + if (Method2 != Method2End) + return false; + + return true; +} + /// Determine structural equivalence of two declarations. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Decl *D1, Decl *D2) { diff --git a/clang/lib/AST/ASTTypeTraits.cpp b/clang/lib/AST/ASTTypeTraits.cpp index b333f4618efb..64823f77e58a 100644 --- a/clang/lib/AST/ASTTypeTraits.cpp +++ b/clang/lib/AST/ASTTypeTraits.cpp @@ -16,6 +16,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/OpenMPClause.h" #include "clang/AST/TypeLoc.h" @@ -52,6 +53,7 @@ const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = { {NKI_None, "Attr"}, #define ATTR(A) {NKI_Attr, #A "Attr"}, #include "clang/Basic/AttrList.inc" + {NKI_None, "ObjCProtocolLoc"}, }; bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const { @@ -193,6 +195,8 @@ void DynTypedNode::print(llvm::raw_ostream &OS, QualType(T, 0).print(OS, PP); else if (const Attr *A = get<Attr>()) A->printPretty(OS, PP); + else if (const ObjCProtocolLoc *P = get<ObjCProtocolLoc>()) + P->getProtocol()->print(OS, PP); else OS << "Unable to print values of type " << NodeKind.asStringRef() << "\n"; } @@ -228,5 +232,7 @@ SourceRange DynTypedNode::getSourceRange() const { return CBS->getSourceRange(); if (const auto *A = get<Attr>()) return A->getRange(); + if (const ObjCProtocolLoc *P = get<ObjCProtocolLoc>()) + return P->getSourceRange(); return SourceRange(); } diff --git a/clang/lib/AST/AttrImpl.cpp b/clang/lib/AST/AttrImpl.cpp index 7b8acfcd92be..c1e7435b22da 100644 --- a/clang/lib/AST/AttrImpl.cpp +++ b/clang/lib/AST/AttrImpl.cpp @@ -168,7 +168,7 @@ OMPDeclareTargetDeclAttr::getActiveAttr(const ValueDecl *VD) { llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(const ValueDecl *VD) { llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr = getActiveAttr(VD); - if (ActiveAttr.hasValue()) + if (ActiveAttr) return ActiveAttr.getValue()->getMapType(); return llvm::None; } @@ -176,7 +176,7 @@ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(const ValueDecl *VD) { llvm::Optional<OMPDeclareTargetDeclAttr::DevTypeTy> OMPDeclareTargetDeclAttr::getDeviceType(const ValueDecl *VD) { llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr = getActiveAttr(VD); - if (ActiveAttr.hasValue()) + if (ActiveAttr) return ActiveAttr.getValue()->getDevType(); return llvm::None; } @@ -184,7 +184,7 @@ OMPDeclareTargetDeclAttr::getDeviceType(const ValueDecl *VD) { llvm::Optional<SourceLocation> OMPDeclareTargetDeclAttr::getLocation(const ValueDecl *VD) { llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr = getActiveAttr(VD); - if (ActiveAttr.hasValue()) + if (ActiveAttr) return ActiveAttr.getValue()->getRange().getBegin(); return llvm::None; } diff --git a/clang/lib/AST/CommentParser.cpp b/clang/lib/AST/CommentParser.cpp index 29983b0a16c3..7bac1fb99b88 100644 --- a/clang/lib/AST/CommentParser.cpp +++ b/clang/lib/AST/CommentParser.cpp @@ -289,22 +289,19 @@ void Parser::parseTParamCommandArgs(TParamCommandComment *TPC, Arg.getText()); } -void Parser::parseBlockCommandArgs(BlockCommandComment *BC, - TextTokenRetokenizer &Retokenizer, - unsigned NumArgs) { - typedef BlockCommandComment::Argument Argument; - Argument *Args = - new (Allocator.Allocate<Argument>(NumArgs)) Argument[NumArgs]; +ArrayRef<Comment::Argument> +Parser::parseCommandArgs(TextTokenRetokenizer &Retokenizer, unsigned NumArgs) { + auto *Args = new (Allocator.Allocate<Comment::Argument>(NumArgs)) + Comment::Argument[NumArgs]; unsigned ParsedArgs = 0; Token Arg; while (ParsedArgs < NumArgs && Retokenizer.lexWord(Arg)) { - Args[ParsedArgs] = Argument(SourceRange(Arg.getLocation(), - Arg.getEndLocation()), - Arg.getText()); + Args[ParsedArgs] = Comment::Argument{ + SourceRange(Arg.getLocation(), Arg.getEndLocation()), Arg.getText()}; ParsedArgs++; } - S.actOnBlockCommandArgs(BC, llvm::makeArrayRef(Args, ParsedArgs)); + return llvm::makeArrayRef(Args, ParsedArgs); } BlockCommandComment *Parser::parseBlockCommand() { @@ -360,7 +357,7 @@ BlockCommandComment *Parser::parseBlockCommand() { else if (TPC) parseTParamCommandArgs(TPC, Retokenizer); else - parseBlockCommandArgs(BC, Retokenizer, Info->NumArgs); + S.actOnBlockCommandArgs(BC, parseCommandArgs(Retokenizer, Info->NumArgs)); Retokenizer.putBackLeftoverTokens(); } @@ -401,32 +398,24 @@ BlockCommandComment *Parser::parseBlockCommand() { InlineCommandComment *Parser::parseInlineCommand() { assert(Tok.is(tok::backslash_command) || Tok.is(tok::at_command)); + const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID()); const Token CommandTok = Tok; consumeToken(); TextTokenRetokenizer Retokenizer(Allocator, *this); + ArrayRef<Comment::Argument> Args = + parseCommandArgs(Retokenizer, Info->NumArgs); - Token ArgTok; - bool ArgTokValid = Retokenizer.lexWord(ArgTok); - - InlineCommandComment *IC; - if (ArgTokValid) { - IC = S.actOnInlineCommand(CommandTok.getLocation(), - CommandTok.getEndLocation(), - CommandTok.getCommandID(), - ArgTok.getLocation(), - ArgTok.getEndLocation(), - ArgTok.getText()); - } else { - IC = S.actOnInlineCommand(CommandTok.getLocation(), - CommandTok.getEndLocation(), - CommandTok.getCommandID()); + InlineCommandComment *IC = S.actOnInlineCommand( + CommandTok.getLocation(), CommandTok.getEndLocation(), + CommandTok.getCommandID(), Args); + if (Args.size() < Info->NumArgs) { Diag(CommandTok.getEndLocation().getLocWithOffset(1), - diag::warn_doc_inline_contents_no_argument) - << CommandTok.is(tok::at_command) - << Traits.getCommandInfo(CommandTok.getCommandID())->Name + diag::warn_doc_inline_command_not_enough_arguments) + << CommandTok.is(tok::at_command) << Info->Name << Args.size() + << Info->NumArgs << SourceRange(CommandTok.getLocation(), CommandTok.getEndLocation()); } diff --git a/clang/lib/AST/CommentSema.cpp b/clang/lib/AST/CommentSema.cpp index 087f103e4931..9b0f03445888 100644 --- a/clang/lib/AST/CommentSema.cpp +++ b/clang/lib/AST/CommentSema.cpp @@ -265,10 +265,8 @@ void Sema::actOnParamCommandParamNameArg(ParamCommandComment *Command, // User didn't provide a direction argument. Command->setDirection(ParamCommandComment::In, /* Explicit = */ false); } - typedef BlockCommandComment::Argument Argument; - Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin, - ArgLocEnd), - Arg); + auto *A = new (Allocator) + Comment::Argument{SourceRange(ArgLocBegin, ArgLocEnd), Arg}; Command->setArgs(llvm::makeArrayRef(A, 1)); } @@ -303,10 +301,8 @@ void Sema::actOnTParamCommandParamNameArg(TParamCommandComment *Command, // Parser will not feed us more arguments than needed. assert(Command->getNumArgs() == 0); - typedef BlockCommandComment::Argument Argument; - Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin, - ArgLocEnd), - Arg); + auto *A = new (Allocator) + Comment::Argument{SourceRange(ArgLocBegin, ArgLocEnd), Arg}; Command->setArgs(llvm::makeArrayRef(A, 1)); if (!isTemplateOrSpecialization()) { @@ -361,37 +357,15 @@ void Sema::actOnTParamCommandFinish(TParamCommandComment *Command, checkBlockCommandEmptyParagraph(Command); } -InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin, - SourceLocation CommandLocEnd, - unsigned CommandID) { - ArrayRef<InlineCommandComment::Argument> Args; +InlineCommandComment * +Sema::actOnInlineCommand(SourceLocation CommandLocBegin, + SourceLocation CommandLocEnd, unsigned CommandID, + ArrayRef<Comment::Argument> Args) { StringRef CommandName = Traits.getCommandInfo(CommandID)->Name; - return new (Allocator) InlineCommandComment( - CommandLocBegin, - CommandLocEnd, - CommandID, - getInlineCommandRenderKind(CommandName), - Args); -} -InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin, - SourceLocation CommandLocEnd, - unsigned CommandID, - SourceLocation ArgLocBegin, - SourceLocation ArgLocEnd, - StringRef Arg) { - typedef InlineCommandComment::Argument Argument; - Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin, - ArgLocEnd), - Arg); - StringRef CommandName = Traits.getCommandInfo(CommandID)->Name; - - return new (Allocator) InlineCommandComment( - CommandLocBegin, - CommandLocEnd, - CommandID, - getInlineCommandRenderKind(CommandName), - llvm::makeArrayRef(A, 1)); + return new (Allocator) + InlineCommandComment(CommandLocBegin, CommandLocEnd, CommandID, + getInlineCommandRenderKind(CommandName), Args); } InlineContentComment *Sema::actOnUnknownCommand(SourceLocation LocBegin, diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp index 5648cf2103d6..1f573346b441 100644 --- a/clang/lib/AST/ComputeDependence.cpp +++ b/clang/lib/AST/ComputeDependence.cpp @@ -26,7 +26,7 @@ ExprDependence clang::computeDependence(FullExpr *E) { } ExprDependence clang::computeDependence(OpaqueValueExpr *E) { - auto D = toExprDependence(E->getType()->getDependence()); + auto D = toExprDependenceForImpliedType(E->getType()->getDependence()); if (auto *S = E->getSourceExpr()) D |= S->getDependence(); assert(!(D & ExprDependence::UnexpandedPack)); @@ -39,8 +39,10 @@ ExprDependence clang::computeDependence(ParenExpr *E) { ExprDependence clang::computeDependence(UnaryOperator *E, const ASTContext &Ctx) { - ExprDependence Dep = toExprDependence(E->getType()->getDependence()) | - E->getSubExpr()->getDependence(); + ExprDependence Dep = + // FIXME: Do we need to look at the type? + toExprDependenceForImpliedType(E->getType()->getDependence()) | + E->getSubExpr()->getDependence(); // C++ [temp.dep.constexpr]p5: // An expression of the form & qualified-id where the qualified-id names a @@ -77,7 +79,7 @@ ExprDependence clang::computeDependence(UnaryExprOrTypeTraitExpr *E) { // Value-dependent if the argument is type-dependent. if (E->isArgumentType()) return turnTypeToValueDependence( - toExprDependence(E->getArgumentType()->getDependence())); + toExprDependenceAsWritten(E->getArgumentType()->getDependence())); auto ArgDeps = E->getArgumentExpr()->getDependence(); auto Deps = ArgDeps & ~ExprDependence::TypeValue; @@ -120,21 +122,36 @@ ExprDependence clang::computeDependence(MatrixSubscriptExpr *E) { } ExprDependence clang::computeDependence(CompoundLiteralExpr *E) { - return toExprDependence(E->getTypeSourceInfo()->getType()->getDependence()) | + return toExprDependenceAsWritten( + E->getTypeSourceInfo()->getType()->getDependence()) | + toExprDependenceForImpliedType(E->getType()->getDependence()) | turnTypeToValueDependence(E->getInitializer()->getDependence()); } -ExprDependence clang::computeDependence(CastExpr *E) { +ExprDependence clang::computeDependence(ImplicitCastExpr *E) { + // We model implicit conversions as combining the dependence of their + // subexpression, apart from its type, with the semantic portion of the + // target type. + ExprDependence D = + toExprDependenceForImpliedType(E->getType()->getDependence()); + if (auto *S = E->getSubExpr()) + D |= S->getDependence() & ~ExprDependence::Type; + return D; +} + +ExprDependence clang::computeDependence(ExplicitCastExpr *E) { // Cast expressions are type-dependent if the type is // dependent (C++ [temp.dep.expr]p3). // Cast expressions are value-dependent if the type is // dependent or if the subexpression is value-dependent. - auto D = toExprDependence(E->getType()->getDependence()); - if (E->getStmtClass() == Stmt::ImplicitCastExprClass) { - // An implicit cast expression doesn't (lexically) contain an - // unexpanded pack, even if its target type does. - D &= ~ExprDependence::UnexpandedPack; - } + // + // Note that we also need to consider the dependence of the actual type here, + // because when the type as written is a deduced type, that type is not + // dependent, but it may be deduced as a dependent type. + ExprDependence D = + toExprDependenceAsWritten( + cast<ExplicitCastExpr>(E)->getTypeAsWritten()->getDependence()) | + toExprDependenceForImpliedType(E->getType()->getDependence()); if (auto *S = E->getSubExpr()) D |= S->getDependence() & ~ExprDependence::Type; return D; @@ -158,7 +175,7 @@ ExprDependence clang::computeDependence(BinaryConditionalOperator *E) { } ExprDependence clang::computeDependence(StmtExpr *E, unsigned TemplateDepth) { - auto D = toExprDependence(E->getType()->getDependence()); + auto D = toExprDependenceForImpliedType(E->getType()->getDependence()); // Propagate dependence of the result. if (const auto *CompoundExprResult = dyn_cast_or_null<ValueStmt>(E->getSubStmt()->getStmtExprResult())) @@ -174,7 +191,8 @@ ExprDependence clang::computeDependence(StmtExpr *E, unsigned TemplateDepth) { } ExprDependence clang::computeDependence(ConvertVectorExpr *E) { - auto D = toExprDependence(E->getType()->getDependence()) | + auto D = toExprDependenceAsWritten( + E->getTypeSourceInfo()->getType()->getDependence()) | E->getSrcExpr()->getDependence(); if (!E->getType()->isDependentType()) D &= ~ExprDependence::Type; @@ -206,14 +224,14 @@ ExprDependence clang::computeDependence(ParenListExpr *P) { } ExprDependence clang::computeDependence(VAArgExpr *E) { - auto D = - toExprDependence(E->getWrittenTypeInfo()->getType()->getDependence()) | - (E->getSubExpr()->getDependence() & ~ExprDependence::Type); + auto D = toExprDependenceAsWritten( + E->getWrittenTypeInfo()->getType()->getDependence()) | + (E->getSubExpr()->getDependence() & ~ExprDependence::Type); return D & ~ExprDependence::Value; } ExprDependence clang::computeDependence(NoInitExpr *E) { - return toExprDependence(E->getType()->getDependence()) & + return toExprDependenceForImpliedType(E->getType()->getDependence()) & (ExprDependence::Instantiation | ExprDependence::Error); } @@ -226,7 +244,7 @@ ExprDependence clang::computeDependence(ArrayInitLoopExpr *E) { } ExprDependence clang::computeDependence(ImplicitValueInitExpr *E) { - return toExprDependence(E->getType()->getDependence()) & + return toExprDependenceForImpliedType(E->getType()->getDependence()) & ExprDependence::Instantiation; } @@ -235,14 +253,16 @@ ExprDependence clang::computeDependence(ExtVectorElementExpr *E) { } ExprDependence clang::computeDependence(BlockExpr *E) { - auto D = toExprDependence(E->getType()->getDependence()); + auto D = toExprDependenceForImpliedType(E->getType()->getDependence()); if (E->getBlockDecl()->isDependentContext()) D |= ExprDependence::Instantiation; - return D & ~ExprDependence::UnexpandedPack; + return D; } ExprDependence clang::computeDependence(AsTypeExpr *E) { - auto D = toExprDependence(E->getType()->getDependence()) | + // FIXME: AsTypeExpr doesn't store the type as written. Assume the expression + // type has identical sugar for now, so is a type-as-written. + auto D = toExprDependenceAsWritten(E->getType()->getDependence()) | E->getSrcExpr()->getDependence(); if (!E->getType()->isDependentType()) D &= ~ExprDependence::Type; @@ -255,15 +275,14 @@ ExprDependence clang::computeDependence(CXXRewrittenBinaryOperator *E) { ExprDependence clang::computeDependence(CXXStdInitializerListExpr *E) { auto D = turnTypeToValueDependence(E->getSubExpr()->getDependence()); - D |= toExprDependence(E->getType()->getDependence()) & - (ExprDependence::Type | ExprDependence::Error); + D |= toExprDependenceForImpliedType(E->getType()->getDependence()); return D; } ExprDependence clang::computeDependence(CXXTypeidExpr *E) { auto D = ExprDependence::None; if (E->isTypeOperand()) - D = toExprDependence( + D = toExprDependenceAsWritten( E->getTypeOperandSourceInfo()->getType()->getDependence()); else D = turnTypeToValueDependence(E->getExprOperand()->getDependence()); @@ -281,7 +300,7 @@ ExprDependence clang::computeDependence(MSPropertySubscriptExpr *E) { ExprDependence clang::computeDependence(CXXUuidofExpr *E) { if (E->isTypeOperand()) - return turnTypeToValueDependence(toExprDependence( + return turnTypeToValueDependence(toExprDependenceAsWritten( E->getTypeOperandSourceInfo()->getType()->getDependence())); return turnTypeToValueDependence(E->getExprOperand()->getDependence()); @@ -290,7 +309,7 @@ ExprDependence clang::computeDependence(CXXUuidofExpr *E) { ExprDependence clang::computeDependence(CXXThisExpr *E) { // 'this' is type-dependent if the class type of the enclosing // member function is dependent (C++ [temp.dep.expr]p2) - auto D = toExprDependence(E->getType()->getDependence()); + auto D = toExprDependenceForImpliedType(E->getType()->getDependence()); assert(!(D & ExprDependence::UnexpandedPack)); return D; } @@ -307,8 +326,10 @@ ExprDependence clang::computeDependence(CXXBindTemporaryExpr *E) { } ExprDependence clang::computeDependence(CXXScalarValueInitExpr *E) { - return toExprDependence(E->getType()->getDependence()) & - ~ExprDependence::TypeValue; + auto D = toExprDependenceForImpliedType(E->getType()->getDependence()); + if (auto *TSI = E->getTypeSourceInfo()) + D |= toExprDependenceAsWritten(TSI->getType()->getDependence()); + return D; } ExprDependence clang::computeDependence(CXXDeleteExpr *E) { @@ -316,7 +337,7 @@ ExprDependence clang::computeDependence(CXXDeleteExpr *E) { } ExprDependence clang::computeDependence(ArrayTypeTraitExpr *E) { - auto D = toExprDependence(E->getQueriedType()->getDependence()); + auto D = toExprDependenceAsWritten(E->getQueriedType()->getDependence()); if (auto *Dim = E->getDimensionExpression()) D |= Dim->getDependence(); return turnTypeToValueDependence(D); @@ -366,7 +387,7 @@ ExprDependence clang::computeDependence(ObjCBoxedExpr *E) { } ExprDependence clang::computeDependence(ObjCEncodeExpr *E) { - return toExprDependence(E->getEncodedType()->getDependence()); + return toExprDependenceAsWritten(E->getEncodedType()->getDependence()); } ExprDependence clang::computeDependence(ObjCIvarRefExpr *E) { @@ -377,7 +398,8 @@ ExprDependence clang::computeDependence(ObjCPropertyRefExpr *E) { if (E->isObjectReceiver()) return E->getBase()->getDependence() & ~ExprDependence::Type; if (E->isSuperReceiver()) - return toExprDependence(E->getSuperReceiverType()->getDependence()) & + return toExprDependenceForImpliedType( + E->getSuperReceiverType()->getDependence()) & ~ExprDependence::TypeValue; assert(E->isClassReceiver()); return ExprDependence::None; @@ -406,19 +428,22 @@ ExprDependence clang::computeDependence(OMPArraySectionExpr *E) { } ExprDependence clang::computeDependence(OMPArrayShapingExpr *E) { - auto D = E->getBase()->getDependence() | - toExprDependence(E->getType()->getDependence()); + auto D = E->getBase()->getDependence(); for (Expr *Dim: E->getDimensions()) if (Dim) - D |= Dim->getDependence(); + D |= turnValueToTypeDependence(Dim->getDependence()); return D; } ExprDependence clang::computeDependence(OMPIteratorExpr *E) { - auto D = toExprDependence(E->getType()->getDependence()); + auto D = toExprDependenceForImpliedType(E->getType()->getDependence()); for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) { - if (auto *VD = cast_or_null<ValueDecl>(E->getIteratorDecl(I))) - D |= toExprDependence(VD->getType()->getDependence()); + if (auto *DD = cast_or_null<DeclaratorDecl>(E->getIteratorDecl(I))) { + // If the type is omitted, it's 'int', and is not dependent in any way. + if (auto *TSI = DD->getTypeSourceInfo()) { + D |= toExprDependenceAsWritten(TSI->getType()->getDependence()); + } + } OMPIteratorExpr::IteratorRange IR = E->getIteratorRange(I); if (Expr *BE = IR.Begin) D |= BE->getDependence(); @@ -451,7 +476,8 @@ ExprDependence clang::computeDependence(DeclRefExpr *E, const ASTContext &Ctx) { if (Decl->isParameterPack()) Deps |= ExprDependence::UnexpandedPack; - Deps |= toExprDependence(Type->getDependence()) & ExprDependence::Error; + Deps |= toExprDependenceForImpliedType(Type->getDependence()) & + ExprDependence::Error; // C++ [temp.dep.expr]p3: // An id-expression is type-dependent if it contains: @@ -547,7 +573,7 @@ ExprDependence clang::computeDependence(RecoveryExpr *E) { // - type-dependent if we don't know the type (fallback to an opaque // dependent type), or the type is known and dependent, or it has // type-dependent subexpressions. - auto D = toExprDependence(E->getType()->getDependence()) | + auto D = toExprDependenceForImpliedType(E->getType()->getDependence()) | ExprDependence::ErrorDependent; // FIXME: remove the type-dependent bit from subexpressions, if the // RecoveryExpr has a non-dependent type. @@ -557,12 +583,12 @@ ExprDependence clang::computeDependence(RecoveryExpr *E) { } ExprDependence clang::computeDependence(SYCLUniqueStableNameExpr *E) { - return toExprDependence(E->getTypeSourceInfo()->getType()->getDependence()); + return toExprDependenceAsWritten( + E->getTypeSourceInfo()->getType()->getDependence()); } ExprDependence clang::computeDependence(PredefinedExpr *E) { - return toExprDependence(E->getType()->getDependence()) & - ~ExprDependence::UnexpandedPack; + return toExprDependenceForImpliedType(E->getType()->getDependence()); } ExprDependence clang::computeDependence(CallExpr *E, @@ -578,8 +604,8 @@ ExprDependence clang::computeDependence(CallExpr *E, } ExprDependence clang::computeDependence(OffsetOfExpr *E) { - auto D = turnTypeToValueDependence( - toExprDependence(E->getTypeSourceInfo()->getType()->getDependence())); + auto D = turnTypeToValueDependence(toExprDependenceAsWritten( + E->getTypeSourceInfo()->getType()->getDependence())); for (unsigned I = 0, N = E->getNumExpressions(); I < N; ++I) D |= turnTypeToValueDependence(E->getIndexExpr(I)->getDependence()); return D; @@ -615,7 +641,7 @@ ExprDependence clang::computeDependence(InitListExpr *E) { } ExprDependence clang::computeDependence(ShuffleVectorExpr *E) { - auto D = toExprDependence(E->getType()->getDependence()); + auto D = toExprDependenceForImpliedType(E->getType()->getDependence()); for (auto *C : llvm::makeArrayRef(E->getSubExprs(), E->getNumSubExprs())) D |= C->getDependence(); return D; @@ -666,9 +692,11 @@ ExprDependence clang::computeDependence(AtomicExpr *A) { } ExprDependence clang::computeDependence(CXXNewExpr *E) { - auto D = toExprDependence(E->getType()->getDependence()); + auto D = toExprDependenceAsWritten( + E->getAllocatedTypeSourceInfo()->getType()->getDependence()); + D |= toExprDependenceForImpliedType(E->getAllocatedType()->getDependence()); auto Size = E->getArraySize(); - if (Size.hasValue() && *Size) + if (Size && *Size) D |= turnTypeToValueDependence((*Size)->getDependence()); if (auto *I = E->getInitializer()) D |= turnTypeToValueDependence(I->getDependence()); @@ -679,11 +707,11 @@ ExprDependence clang::computeDependence(CXXNewExpr *E) { ExprDependence clang::computeDependence(CXXPseudoDestructorExpr *E) { auto D = E->getBase()->getDependence(); - if (!E->getDestroyedType().isNull()) - D |= toExprDependence(E->getDestroyedType()->getDependence()); + if (auto *TSI = E->getDestroyedTypeInfo()) + D |= toExprDependenceAsWritten(TSI->getType()->getDependence()); if (auto *ST = E->getScopeTypeInfo()) D |= turnTypeToValueDependence( - toExprDependence(ST->getType()->getDependence())); + toExprDependenceAsWritten(ST->getType()->getDependence())); if (auto *Q = E->getQualifier()) D |= toExprDependence(Q->getDependence() & ~NestedNameSpecifierDependence::Dependent); @@ -738,12 +766,20 @@ ExprDependence clang::computeDependence(DependentScopeDeclRefExpr *E) { } ExprDependence clang::computeDependence(CXXConstructExpr *E) { - auto D = toExprDependence(E->getType()->getDependence()); + ExprDependence D = + toExprDependenceForImpliedType(E->getType()->getDependence()); for (auto *A : E->arguments()) D |= A->getDependence() & ~ExprDependence::Type; return D; } +ExprDependence clang::computeDependence(CXXTemporaryObjectExpr *E) { + CXXConstructExpr *BaseE = E; + return toExprDependenceAsWritten( + E->getTypeSourceInfo()->getType()->getDependence()) | + computeDependence(BaseE); +} + ExprDependence clang::computeDependence(CXXDefaultInitExpr *E) { return E->getExpr()->getDependence(); } @@ -754,7 +790,7 @@ ExprDependence clang::computeDependence(CXXDefaultArgExpr *E) { ExprDependence clang::computeDependence(LambdaExpr *E, bool ContainsUnexpandedParameterPack) { - auto D = toExprDependence(E->getType()->getDependence()); + auto D = toExprDependenceForImpliedType(E->getType()->getDependence()); if (ContainsUnexpandedParameterPack) D |= ExprDependence::UnexpandedPack; return D; @@ -762,7 +798,8 @@ ExprDependence clang::computeDependence(LambdaExpr *E, ExprDependence clang::computeDependence(CXXUnresolvedConstructExpr *E) { auto D = ExprDependence::ValueInstantiation; - D |= toExprDependence(E->getType()->getDependence()); + D |= toExprDependenceAsWritten(E->getTypeAsWritten()->getDependence()); + D |= toExprDependenceForImpliedType(E->getType()->getDependence()); for (auto *A : E->arguments()) D |= A->getDependence() & (ExprDependence::UnexpandedPack | ExprDependence::Error); @@ -797,8 +834,8 @@ ExprDependence clang::computeDependence(CXXFoldExpr *E) { ExprDependence clang::computeDependence(TypeTraitExpr *E) { auto D = ExprDependence::None; for (const auto *A : E->getArgs()) - D |= - toExprDependence(A->getType()->getDependence()) & ~ExprDependence::Type; + D |= toExprDependenceAsWritten(A->getType()->getDependence()) & + ~ExprDependence::Type; return D; } @@ -845,7 +882,7 @@ ExprDependence clang::computeDependence(ObjCMessageExpr *E) { if (auto *R = E->getInstanceReceiver()) D |= R->getDependence(); else - D |= toExprDependence(E->getType()->getDependence()); + D |= toExprDependenceForImpliedType(E->getType()->getDependence()); for (auto *A : E->arguments()) D |= A->getDependence(); return D; diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index b2ee34f20cf7..5e5101203e6c 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -30,6 +30,8 @@ #include "clang/AST/ODRHash.h" #include "clang/AST/PrettyDeclStackTrace.h" #include "clang/AST/PrettyPrinter.h" +#include "clang/AST/Randstruct.h" +#include "clang/AST/RecordLayout.h" #include "clang/AST/Redeclarable.h" #include "clang/AST/Stmt.h" #include "clang/AST/TemplateBase.h" @@ -391,11 +393,18 @@ void LinkageComputer::mergeTemplateLV( bool considerVisibility = shouldConsiderTemplateVisibility(fn, specInfo); - // Merge information from the template parameters. FunctionTemplateDecl *temp = specInfo->getTemplate(); - LinkageInfo tempLV = - getLVForTemplateParameterList(temp->getTemplateParameters(), computation); - LV.mergeMaybeWithVisibility(tempLV, considerVisibility); + + // Merge information from the template declaration. + LinkageInfo tempLV = getLVForDecl(temp, computation); + // The linkage of the specialization should be consistent with the + // template declaration. + LV.setLinkage(tempLV.getLinkage()); + + // Merge information from the template parameters. + LinkageInfo paramsLV = + getLVForTemplateParameterList(temp->getTemplateParameters(), computation); + LV.mergeMaybeWithVisibility(paramsLV, considerVisibility); // Merge information from the template arguments. const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments; @@ -579,6 +588,7 @@ static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) { // FIXME: Handle isModulePrivate. switch (D->getModuleOwnershipKind()) { case Decl::ModuleOwnershipKind::Unowned: + case Decl::ModuleOwnershipKind::ReachableWhenImported: case Decl::ModuleOwnershipKind::ModulePrivate: return false; case Decl::ModuleOwnershipKind::Visible: @@ -589,11 +599,12 @@ static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) { } static LinkageInfo getInternalLinkageFor(const NamedDecl *D) { - // Internal linkage declarations within a module interface unit are modeled - // as "module-internal linkage", which means that they have internal linkage - // formally but can be indirectly accessed from outside the module via inline - // functions and templates defined within the module. - if (isInModulePurview(D)) + // (for the modules ts) Internal linkage declarations within a module + // interface unit are modeled as "module-internal linkage", which means that + // they have internal linkage formally but can be indirectly accessed from + // outside the module via inline functions and templates defined within the + // module. + if (isInModulePurview(D) && D->getASTContext().getLangOpts().ModulesTS) return LinkageInfo(ModuleInternalLinkage, DefaultVisibility, false); return LinkageInfo::internal(); @@ -1540,6 +1551,11 @@ LinkageInfo LinkageComputer::getDeclLinkageAndVisibility(const NamedDecl *D) { } Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const { + if (isa<NamespaceDecl>(this)) + // Namespaces never have module linkage. It is the entities within them + // that [may] do. + return nullptr; + Module *M = getOwningModule(); if (!M) return nullptr; @@ -1550,24 +1566,28 @@ Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const { return nullptr; case Module::ModuleInterfaceUnit: + case Module::ModulePartitionInterface: + case Module::ModulePartitionImplementation: return M; + case Module::ModuleHeaderUnit: case Module::GlobalModuleFragment: { // External linkage declarations in the global module have no owning module // for linkage purposes. But internal linkage declarations in the global // module fragment of a particular module are owned by that module for // linkage purposes. + // FIXME: p1815 removes the need for this distinction -- there are no + // internal linkage declarations that need to be referred to from outside + // this TU. if (IgnoreLinkage) return nullptr; bool InternalLinkage; if (auto *ND = dyn_cast<NamedDecl>(this)) InternalLinkage = !ND->hasExternalFormalLinkage(); - else { - auto *NSD = dyn_cast<NamespaceDecl>(this); - InternalLinkage = (NSD && NSD->isAnonymousNamespace()) || - isInAnonymousNamespace(); - } - return InternalLinkage ? M->Parent : nullptr; + else + InternalLinkage = isInAnonymousNamespace(); + return InternalLinkage ? M->Kind == Module::ModuleHeaderUnit ? M : M->Parent + : nullptr; } case Module::PrivateModuleFragment: @@ -1832,7 +1852,7 @@ bool NamedDecl::hasLinkage() const { NamedDecl *NamedDecl::getUnderlyingDeclImpl() { NamedDecl *ND = this; - while (auto *UD = dyn_cast<UsingShadowDecl>(ND)) + if (auto *UD = dyn_cast<UsingShadowDecl>(ND)) ND = UD->getTargetDecl(); if (auto *AD = dyn_cast<ObjCCompatibleAliasDecl>(ND)) @@ -2018,7 +2038,7 @@ const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) { VarDecl::VarDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, + const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass SC) : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), redeclarable_base(C) { @@ -2033,10 +2053,9 @@ VarDecl::VarDecl(Kind DK, ASTContext &C, DeclContext *DC, // Everything else is implicitly initialized to false. } -VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation StartL, SourceLocation IdL, - IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S) { +VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartL, + SourceLocation IdL, const IdentifierInfo *Id, + QualType T, TypeSourceInfo *TInfo, StorageClass S) { return new (C, DC) VarDecl(Var, C, DC, StartL, IdL, Id, T, TInfo, S); } @@ -2705,6 +2724,42 @@ VarDecl::needsDestruction(const ASTContext &Ctx) const { return getType().isDestructedType(); } +bool VarDecl::hasFlexibleArrayInit(const ASTContext &Ctx) const { + assert(hasInit() && "Expect initializer to check for flexible array init"); + auto *Ty = getType()->getAs<RecordType>(); + if (!Ty || !Ty->getDecl()->hasFlexibleArrayMember()) + return false; + auto *List = dyn_cast<InitListExpr>(getInit()->IgnoreParens()); + if (!List) + return false; + const Expr *FlexibleInit = List->getInit(List->getNumInits() - 1); + auto InitTy = Ctx.getAsConstantArrayType(FlexibleInit->getType()); + if (!InitTy) + return false; + return InitTy->getSize() != 0; +} + +CharUnits VarDecl::getFlexibleArrayInitChars(const ASTContext &Ctx) const { + assert(hasInit() && "Expect initializer to check for flexible array init"); + auto *Ty = getType()->getAs<RecordType>(); + if (!Ty || !Ty->getDecl()->hasFlexibleArrayMember()) + return CharUnits::Zero(); + auto *List = dyn_cast<InitListExpr>(getInit()->IgnoreParens()); + if (!List) + return CharUnits::Zero(); + const Expr *FlexibleInit = List->getInit(List->getNumInits() - 1); + auto InitTy = Ctx.getAsConstantArrayType(FlexibleInit->getType()); + if (!InitTy) + return CharUnits::Zero(); + CharUnits FlexibleArraySize = Ctx.getTypeSizeInChars(InitTy); + const ASTRecordLayout &RL = Ctx.getASTRecordLayout(Ty->getDecl()); + CharUnits FlexibleArrayOffset = + Ctx.toCharUnitsFromBits(RL.getFieldOffset(RL.getFieldCount() - 1)); + if (FlexibleArrayOffset + FlexibleArraySize < RL.getSize()) + return CharUnits::Zero(); + return FlexibleArrayOffset + FlexibleArraySize - RL.getSize(); +} + MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const { if (isStaticDataMember()) // FIXME: Remove ? @@ -2813,7 +2868,8 @@ Expr *ParmVarDecl::getDefaultArg() { Expr *Arg = getInit(); if (auto *E = dyn_cast_or_null<FullExpr>(Arg)) - return E->getSubExpr(); + if (!isa<ConstantExpr>(E)) + return E->getSubExpr(); return Arg; } @@ -2900,6 +2956,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, FunctionDeclBits.IsDefaulted = false; FunctionDeclBits.IsExplicitlyDefaulted = false; FunctionDeclBits.HasDefaultedFunctionInfo = false; + FunctionDeclBits.IsIneligibleOrNotSelected = false; FunctionDeclBits.HasImplicitReturnZero = false; FunctionDeclBits.IsLateTemplateParsed = false; FunctionDeclBits.ConstexprKind = static_cast<uint64_t>(ConstexprKind); @@ -4301,6 +4358,7 @@ TagDecl::TagDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC, setEmbeddedInDeclarator(false); setFreeStanding(false); setCompleteDefinitionRequired(false); + TagDeclBits.IsThisDeclarationADemotedDefinition = false; } SourceLocation TagDecl::getOuterLocStart() const { @@ -4566,6 +4624,7 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C, setHasNonTrivialToPrimitiveCopyCUnion(false); setParamDestroyedInCallee(false); setArgPassingRestrictions(APK_CanPassInRegs); + setIsRandomized(false); } RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, @@ -4649,6 +4708,12 @@ bool RecordDecl::isMsStruct(const ASTContext &C) const { return hasAttr<MSStructAttr>() || C.getLangOpts().MSBitfields == 1; } +void RecordDecl::reorderDecls(const SmallVectorImpl<Decl *> &Decls) { + std::tie(FirstDecl, LastDecl) = DeclContext::BuildDeclChain(Decls, false); + LastDecl->NextInContextAndBits.setPointer(nullptr); + setIsRandomized(true); +} + void RecordDecl::LoadFieldsFromExternalStorage() const { ExternalASTSource *Source = getASTContext().getExternalSource(); assert(hasExternalLexicalStorage() && Source && "No external storage?"); diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 9ee1cc083086..13dd6da3f24f 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -838,6 +838,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case ExternCContext: case Decomposition: case MSGuid: + case UnnamedGlobalConstant: case TemplateParamObject: case UsingDirective: @@ -1161,6 +1162,8 @@ bool DeclContext::isDependentContext() const { if (Record->isDependentLambda()) return true; + if (Record->isNeverDependentLambda()) + return false; } if (const auto *Function = dyn_cast<FunctionDecl>(this)) { @@ -1534,7 +1537,11 @@ void DeclContext::removeDecl(Decl *D) { if (Map) { StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName()); assert(Pos != Map->end() && "no lookup entry for decl"); - Pos->second.remove(ND); + StoredDeclsList &List = Pos->second; + List.remove(ND); + // Clean up the entry if there are no more decls. + if (List.isNull()) + Map->erase(Pos); } } while (DC->isTransparentContext() && (DC = DC->getParent())); } diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 0cf6e60b2a6c..6fc9a86bc3cf 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -146,16 +146,16 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, CXXRecordDecl * CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, TypeSourceInfo *Info, SourceLocation Loc, - bool Dependent, bool IsGeneric, + unsigned DependencyKind, bool IsGeneric, LambdaCaptureDefault CaptureDefault) { auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TTK_Class, C, DC, Loc, Loc, nullptr, nullptr); R->setBeingDefined(true); - R->DefinitionData = - new (C) struct LambdaDefinitionData(R, Info, Dependent, IsGeneric, - CaptureDefault); + R->DefinitionData = new (C) struct LambdaDefinitionData( + R, Info, DependencyKind, IsGeneric, CaptureDefault); R->setMayHaveOutOfDateDef(false); R->setImplicit(true); + C.getTypeDeclType(R, /*PrevDecl=*/nullptr); return R; } @@ -825,29 +825,11 @@ void CXXRecordDecl::addedMember(Decl *D) { data().HasInheritedDefaultConstructor = true; } - // Handle destructors. - if (const auto *DD = dyn_cast<CXXDestructorDecl>(D)) { - SMKind |= SMF_Destructor; - - if (DD->isUserProvided()) - data().HasIrrelevantDestructor = false; - // If the destructor is explicitly defaulted and not trivial or not public - // or if the destructor is deleted, we clear HasIrrelevantDestructor in - // finishedDefaultedOrDeletedMember. - - // C++11 [class.dtor]p5: - // A destructor is trivial if [...] the destructor is not virtual. - if (DD->isVirtual()) { - data().HasTrivialSpecialMembers &= ~SMF_Destructor; - data().HasTrivialSpecialMembersForCall &= ~SMF_Destructor; - } - - if (DD->isNoReturn()) - data().IsAnyDestructorNoReturn = true; - } - // Handle member functions. if (const auto *Method = dyn_cast<CXXMethodDecl>(D)) { + if (isa<CXXDestructorDecl>(D)) + SMKind |= SMF_Destructor; + if (Method->isCopyAssignmentOperator()) { SMKind |= SMF_CopyAssignment; @@ -893,31 +875,9 @@ void CXXRecordDecl::addedMember(Decl *D) { data().HasTrivialSpecialMembersForCall &= data().DeclaredSpecialMembers | ~SMKind; - if (!Method->isImplicit() && !Method->isUserProvided()) { - // This method is user-declared but not user-provided. We can't work out - // whether it's trivial yet (not until we get to the end of the class). - // We'll handle this method in finishedDefaultedOrDeletedMember. - } else if (Method->isTrivial()) { - data().HasTrivialSpecialMembers |= SMKind; - data().HasTrivialSpecialMembersForCall |= SMKind; - } else if (Method->isTrivialForCall()) { - data().HasTrivialSpecialMembersForCall |= SMKind; - data().DeclaredNonTrivialSpecialMembers |= SMKind; - } else { - data().DeclaredNonTrivialSpecialMembers |= SMKind; - // If this is a user-provided function, do not set - // DeclaredNonTrivialSpecialMembersForCall here since we don't know - // yet whether the method would be considered non-trivial for the - // purpose of calls (attribute "trivial_abi" can be dropped from the - // class later, which can change the special method's triviality). - if (!Method->isUserProvided()) - data().DeclaredNonTrivialSpecialMembersForCall |= SMKind; - } - // Note when we have declared a declared special member, and suppress the // implicit declaration of this special member. data().DeclaredSpecialMembers |= SMKind; - if (!Method->isImplicit()) { data().UserDeclaredSpecialMembers |= SMKind; @@ -934,6 +894,12 @@ void CXXRecordDecl::addedMember(Decl *D) { // This is an extension in C++03. data().PlainOldData = false; } + // We delay updating destructor relevant properties until + // addedSelectedDestructor. + // FIXME: Defer this for the other special member functions as well. + if (!Method->isIneligibleOrNotSelected()) { + addedEligibleSpecialMemberFunction(Method, SMKind); + } } return; @@ -1393,6 +1359,54 @@ void CXXRecordDecl::addedMember(Decl *D) { } } +void CXXRecordDecl::addedSelectedDestructor(CXXDestructorDecl *DD) { + DD->setIneligibleOrNotSelected(false); + addedEligibleSpecialMemberFunction(DD, SMF_Destructor); +} + +void CXXRecordDecl::addedEligibleSpecialMemberFunction(const CXXMethodDecl *MD, + unsigned SMKind) { + if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) { + if (DD->isUserProvided()) + data().HasIrrelevantDestructor = false; + // If the destructor is explicitly defaulted and not trivial or not public + // or if the destructor is deleted, we clear HasIrrelevantDestructor in + // finishedDefaultedOrDeletedMember. + + // C++11 [class.dtor]p5: + // A destructor is trivial if [...] the destructor is not virtual. + if (DD->isVirtual()) { + data().HasTrivialSpecialMembers &= ~SMF_Destructor; + data().HasTrivialSpecialMembersForCall &= ~SMF_Destructor; + } + + if (DD->isNoReturn()) + data().IsAnyDestructorNoReturn = true; + } + + if (!MD->isImplicit() && !MD->isUserProvided()) { + // This method is user-declared but not user-provided. We can't work + // out whether it's trivial yet (not until we get to the end of the + // class). We'll handle this method in + // finishedDefaultedOrDeletedMember. + } else if (MD->isTrivial()) { + data().HasTrivialSpecialMembers |= SMKind; + data().HasTrivialSpecialMembersForCall |= SMKind; + } else if (MD->isTrivialForCall()) { + data().HasTrivialSpecialMembersForCall |= SMKind; + data().DeclaredNonTrivialSpecialMembers |= SMKind; + } else { + data().DeclaredNonTrivialSpecialMembers |= SMKind; + // If this is a user-provided function, do not set + // DeclaredNonTrivialSpecialMembersForCall here since we don't know + // yet whether the method would be considered non-trivial for the + // purpose of calls (attribute "trivial_abi" can be dropped from the + // class later, which can change the special method's triviality). + if (!MD->isUserProvided()) + data().DeclaredNonTrivialSpecialMembersForCall |= SMKind; + } +} + void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) { assert(!D->isImplicit() && !D->isUserProvided()); @@ -1895,7 +1909,14 @@ CXXDestructorDecl *CXXRecordDecl::getDestructor() const { DeclContext::lookup_result R = lookup(Name); - return R.empty() ? nullptr : dyn_cast<CXXDestructorDecl>(R.front()); + // If a destructor was marked as not selected, we skip it. We don't always + // have a selected destructor: dependent types, unnamed structs. + for (auto *Decl : R) { + auto* DD = dyn_cast<CXXDestructorDecl>(Decl); + if (DD && !DD->isIneligibleOrNotSelected()) + return DD; + } + return nullptr; } static bool isDeclContextInNamespace(const DeclContext *DC) { @@ -2968,8 +2989,10 @@ UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC, BaseUsingDecl *Introducer, NamedDecl *Target) : NamedDecl(K, DC, Loc, Name), redeclarable_base(C), UsingOrNextShadow(Introducer) { - if (Target) + if (Target) { + assert(!isa<UsingShadowDecl>(Target)); setTargetDecl(Target); + } setImplicit(); } @@ -3363,6 +3386,38 @@ APValue &MSGuidDecl::getAsAPValue() const { return APVal; } +void UnnamedGlobalConstantDecl::anchor() {} + +UnnamedGlobalConstantDecl::UnnamedGlobalConstantDecl(const ASTContext &C, + DeclContext *DC, + QualType Ty, + const APValue &Val) + : ValueDecl(Decl::UnnamedGlobalConstant, DC, SourceLocation(), + DeclarationName(), Ty), + Value(Val) { + // Cleanup the embedded APValue if required (note that our destructor is never + // run) + if (Value.needsCleanup()) + C.addDestruction(&Value); +} + +UnnamedGlobalConstantDecl * +UnnamedGlobalConstantDecl::Create(const ASTContext &C, QualType T, + const APValue &Value) { + DeclContext *DC = C.getTranslationUnitDecl(); + return new (C, DC) UnnamedGlobalConstantDecl(C, DC, T, Value); +} + +UnnamedGlobalConstantDecl * +UnnamedGlobalConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) + UnnamedGlobalConstantDecl(C, nullptr, QualType(), APValue()); +} + +void UnnamedGlobalConstantDecl::printName(llvm::raw_ostream &OS) const { + OS << "unnamed-global-constant"; +} + static const char *getAccessName(AccessSpecifier AS) { switch (AS) { case AS_none: diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index f15dd78929e2..15c545b59c81 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -1647,6 +1647,11 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { ObjCIvarDecl *curIvar = nullptr; if (!data().IvarList) { + // Force ivar deserialization upfront, before building IvarList. + (void)ivar_empty(); + for (const auto *Ext : known_extensions()) { + (void)Ext->ivar_empty(); + } if (!ivar_empty()) { ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end(); data().IvarList = *I; ++I; @@ -1838,8 +1843,8 @@ ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { ObjCIvarDecl::None, nullptr, false); } -const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const { - const auto *DC = cast<ObjCContainerDecl>(getDeclContext()); +ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() { + auto *DC = cast<ObjCContainerDecl>(getDeclContext()); switch (DC->getKind()) { default: @@ -1849,7 +1854,7 @@ const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const { // Ivars can only appear in class extension categories. case ObjCCategory: { - const auto *CD = cast<ObjCCategoryDecl>(DC); + auto *CD = cast<ObjCCategoryDecl>(DC); assert(CD->IsClassExtension() && "invalid container for ivar!"); return CD->getClassInterface(); } diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index c3f1d1544f79..c6a392c9c01b 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -680,6 +680,10 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (FT->isVariadic()) { if (D->getNumParams()) POut << ", "; POut << "..."; + } else if (!D->getNumParams() && !Context.getLangOpts().CPlusPlus) { + // The function has a prototype, so it needs to retain the prototype + // in C. + POut << "void"; } } else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) { for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { @@ -891,12 +895,15 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) { Expr *Init = D->getInit(); if (!Policy.SuppressInitializers && Init) { bool ImplicitInit = false; - if (CXXConstructExpr *Construct = - dyn_cast<CXXConstructExpr>(Init->IgnoreImplicit())) { + if (D->isCXXForRangeDecl()) { + // FIXME: We should print the range expression instead. + ImplicitInit = true; + } else if (CXXConstructExpr *Construct = + dyn_cast<CXXConstructExpr>(Init->IgnoreImplicit())) { if (D->getInitStyle() == VarDecl::CallInit && !Construct->isListInitialization()) { ImplicitInit = Construct->getNumArgs() == 0 || - Construct->getArg(0)->isDefaultArgument(); + Construct->getArg(0)->isDefaultArgument(); } } if (!ImplicitInit) { diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 223f06b9db1c..e7e5f355809b 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -28,6 +28,7 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/None.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" @@ -1098,7 +1099,13 @@ FriendTemplateDecl::Create(ASTContext &Context, DeclContext *DC, SourceLocation L, MutableArrayRef<TemplateParameterList *> Params, FriendUnion Friend, SourceLocation FLoc) { - return new (Context, DC) FriendTemplateDecl(DC, L, Params, Friend, FLoc); + TemplateParameterList **TPL = nullptr; + if (!Params.empty()) { + TPL = new (Context) TemplateParameterList *[Params.size()]; + llvm::copy(Params, TPL); + } + return new (Context, DC) + FriendTemplateDecl(DC, L, TPL, Params.size(), Friend, FLoc); } FriendTemplateDecl *FriendTemplateDecl::CreateDeserialized(ASTContext &C, @@ -1328,10 +1335,14 @@ VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const { void VarTemplateSpecializationDecl::setTemplateArgsInfo( const TemplateArgumentListInfo &ArgsInfo) { - TemplateArgsInfo.setLAngleLoc(ArgsInfo.getLAngleLoc()); - TemplateArgsInfo.setRAngleLoc(ArgsInfo.getRAngleLoc()); - for (const TemplateArgumentLoc &Loc : ArgsInfo.arguments()) - TemplateArgsInfo.addArgument(Loc); + TemplateArgsInfo = + ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo); +} + +void VarTemplateSpecializationDecl::setTemplateArgsInfo( + const ASTTemplateArgumentListInfo *ArgsInfo) { + TemplateArgsInfo = + ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo); } //===----------------------------------------------------------------------===// @@ -1507,12 +1518,20 @@ void TemplateParamObjectDecl::printName(llvm::raw_ostream &OS) const { } void TemplateParamObjectDecl::printAsExpr(llvm::raw_ostream &OS) const { - const ASTContext &Ctx = getASTContext(); - getType().getUnqualifiedType().print(OS, Ctx.getPrintingPolicy()); - printAsInit(OS); + printAsExpr(OS, getASTContext().getPrintingPolicy()); +} + +void TemplateParamObjectDecl::printAsExpr(llvm::raw_ostream &OS, + const PrintingPolicy &Policy) const { + getType().getUnqualifiedType().print(OS, Policy); + printAsInit(OS, Policy); } void TemplateParamObjectDecl::printAsInit(llvm::raw_ostream &OS) const { - const ASTContext &Ctx = getASTContext(); - getValue().printPretty(OS, Ctx, getType()); + printAsInit(OS, getASTContext().getPrintingPolicy()); +} + +void TemplateParamObjectDecl::printAsInit(llvm::raw_ostream &OS, + const PrintingPolicy &Policy) const { + getValue().printPretty(OS, Policy, getType(), &getASTContext()); } diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 45e94847caee..ca477e6500c5 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -31,6 +31,7 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Lexer.h" #include "clang/Lex/LiteralSupport.h" +#include "clang/Lex/Preprocessor.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" @@ -960,40 +961,10 @@ void CharacterLiteral::print(unsigned Val, CharacterKind Kind, break; } - switch (Val) { - case '\\': - OS << "'\\\\'"; - break; - case '\'': - OS << "'\\''"; - break; - case '\a': - // TODO: K&R: the meaning of '\\a' is different in traditional C - OS << "'\\a'"; - break; - case '\b': - OS << "'\\b'"; - break; - // Nonstandard escape sequence. - /*case '\e': - OS << "'\\e'"; - 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; - default: + StringRef Escaped = escapeCStyle<EscapeChar::Single>(Val); + if (!Escaped.empty()) { + OS << "'" << Escaped << "'"; + } else { // A character literal might be sign-extended, which // would result in an invalid \U escape sequence. // FIXME: multicharacter literals such as '\xFF\xFF\xFF\xFF' @@ -1052,7 +1023,7 @@ unsigned StringLiteral::mapCharByteWidth(TargetInfo const &Target, StringKind SK) { unsigned CharByteWidth = 0; switch (SK) { - case Ascii: + case Ordinary: case UTF8: CharByteWidth = Target.getCharWidth(); break; @@ -1152,7 +1123,8 @@ StringLiteral *StringLiteral::CreateEmpty(const ASTContext &Ctx, void StringLiteral::outputString(raw_ostream &OS) const { switch (getKind()) { - case Ascii: break; // no prefix. + case Ordinary: + break; // no prefix. case Wide: OS << 'L'; break; case UTF8: OS << "u8"; break; case UTF16: OS << 'u'; break; @@ -1163,8 +1135,9 @@ void StringLiteral::outputString(raw_ostream &OS) const { unsigned LastSlashX = getLength(); for (unsigned I = 0, N = getLength(); I != N; ++I) { - switch (uint32_t Char = getCodeUnit(I)) { - default: + uint32_t Char = getCodeUnit(I); + StringRef Escaped = escapeCStyle<EscapeChar::Double>(Char); + if (Escaped.empty()) { // FIXME: Convert UTF-8 back to codepoints before rendering. // Convert UTF-16 surrogate pairs back to codepoints before rendering. @@ -1192,7 +1165,7 @@ void StringLiteral::outputString(raw_ostream &OS) const { for (/**/; Shift >= 0; Shift -= 4) OS << Hex[(Char >> Shift) & 15]; LastSlashX = I; - break; + continue; } if (Char > 0xffff) @@ -1205,7 +1178,7 @@ void StringLiteral::outputString(raw_ostream &OS) const { << Hex[(Char >> 8) & 15] << Hex[(Char >> 4) & 15] << Hex[(Char >> 0) & 15]; - break; + continue; } // If we used \x... for the previous character, and this character is a @@ -1230,17 +1203,9 @@ void StringLiteral::outputString(raw_ostream &OS) const { << (char)('0' + ((Char >> 6) & 7)) << (char)('0' + ((Char >> 3) & 7)) << (char)('0' + ((Char >> 0) & 7)); - break; - // Handle some common non-printable cases to make dumps prettier. - case '\\': OS << "\\\\"; break; - case '"': OS << "\\\""; 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; + } else { + // Handle some common non-printable cases to make dumps prettier. + OS << Escaped; } } OS << '"'; @@ -1267,7 +1232,7 @@ StringLiteral::getLocationOfByte(unsigned ByteNo, const SourceManager &SM, const LangOptions &Features, const TargetInfo &Target, unsigned *StartToken, unsigned *StartTokenByteOffset) const { - assert((getKind() == StringLiteral::Ascii || + assert((getKind() == StringLiteral::Ordinary || getKind() == StringLiteral::UTF8) && "Only narrow string literals are currently supported"); @@ -1515,8 +1480,7 @@ Decl *Expr::getReferencedDeclOfCallee() { /// If this is a call to a builtin, return the builtin ID. If not, return 0. unsigned CallExpr::getBuiltinCallee() const { - auto *FDecl = - dyn_cast_or_null<FunctionDecl>(getCallee()->getReferencedDeclOfCallee()); + auto *FDecl = getDirectCallee(); return FDecl ? FDecl->getBuiltinID() : 0; } @@ -1559,6 +1523,11 @@ const Attr *CallExpr::getUnusedResultAttr(const ASTContext &Ctx) const { if (const auto *A = TD->getAttr<WarnUnusedResultAttr>()) return A; + for (const auto *TD = getCallReturnType(Ctx)->getAs<TypedefType>(); TD; + TD = TD->desugar()->getAs<TypedefType>()) + if (const auto *A = TD->getDecl()->getAttr<WarnUnusedResultAttr>()) + return A; + // Otherwise, see if the callee is marked nodiscard and return that attribute // instead. const Decl *D = getCalleeDecl(); @@ -1899,51 +1868,49 @@ const char *CastExpr::getCastKindName(CastKind CK) { } namespace { - const Expr *skipImplicitTemporary(const Expr *E) { - // Skip through reference binding to temporary. - if (auto *Materialize = dyn_cast<MaterializeTemporaryExpr>(E)) - E = Materialize->getSubExpr(); +// Skip over implicit nodes produced as part of semantic analysis. +// Designed for use with IgnoreExprNodes. +Expr *ignoreImplicitSemaNodes(Expr *E) { + if (auto *Materialize = dyn_cast<MaterializeTemporaryExpr>(E)) + return Materialize->getSubExpr(); - // Skip any temporary bindings; they're implicit. - if (auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E)) - E = Binder->getSubExpr(); + if (auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E)) + return Binder->getSubExpr(); - return E; - } + if (auto *Full = dyn_cast<FullExpr>(E)) + return Full->getSubExpr(); + + return E; } +} // namespace Expr *CastExpr::getSubExprAsWritten() { const Expr *SubExpr = nullptr; - const CastExpr *E = this; - do { - SubExpr = skipImplicitTemporary(E->getSubExpr()); + + for (const CastExpr *E = this; E; E = dyn_cast<ImplicitCastExpr>(SubExpr)) { + SubExpr = IgnoreExprNodes(E->getSubExpr(), ignoreImplicitSemaNodes); // Conversions by constructor and conversion functions have a // subexpression describing the call; strip it off. - if (E->getCastKind() == CK_ConstructorConversion) - SubExpr = - skipImplicitTemporary(cast<CXXConstructExpr>(SubExpr->IgnoreImplicit())->getArg(0)); - else if (E->getCastKind() == CK_UserDefinedConversion) { - SubExpr = SubExpr->IgnoreImplicit(); - assert((isa<CXXMemberCallExpr>(SubExpr) || - isa<BlockExpr>(SubExpr)) && + if (E->getCastKind() == CK_ConstructorConversion) { + SubExpr = IgnoreExprNodes(cast<CXXConstructExpr>(SubExpr)->getArg(0), + ignoreImplicitSemaNodes); + } else if (E->getCastKind() == CK_UserDefinedConversion) { + assert((isa<CXXMemberCallExpr>(SubExpr) || isa<BlockExpr>(SubExpr)) && "Unexpected SubExpr for CK_UserDefinedConversion."); if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SubExpr)) SubExpr = MCE->getImplicitObjectArgument(); } + } - // If the subexpression we're left with is an implicit cast, look - // through that, too. - } while ((E = dyn_cast<ImplicitCastExpr>(SubExpr))); - - return const_cast<Expr*>(SubExpr); + return const_cast<Expr *>(SubExpr); } NamedDecl *CastExpr::getConversionFunction() const { const Expr *SubExpr = nullptr; for (const CastExpr *E = this; E; E = dyn_cast<ImplicitCastExpr>(SubExpr)) { - SubExpr = skipImplicitTemporary(E->getSubExpr()); + SubExpr = IgnoreExprNodes(E->getSubExpr(), ignoreImplicitSemaNodes); if (E->getCastKind() == CK_ConstructorConversion) return cast<CXXConstructExpr>(SubExpr)->getConstructor(); @@ -2175,26 +2142,11 @@ bool BinaryOperator::isNullPointerArithmeticExtension(ASTContext &Ctx, return true; } -static QualType getDecayedSourceLocExprType(const ASTContext &Ctx, - SourceLocExpr::IdentKind Kind) { - switch (Kind) { - case SourceLocExpr::File: - case SourceLocExpr::Function: { - QualType ArrTy = Ctx.getStringLiteralArrayType(Ctx.CharTy, 0); - return Ctx.getPointerType(ArrTy->getAsArrayTypeUnsafe()->getElementType()); - } - case SourceLocExpr::Line: - case SourceLocExpr::Column: - return Ctx.UnsignedIntTy; - } - llvm_unreachable("unhandled case"); -} - SourceLocExpr::SourceLocExpr(const ASTContext &Ctx, IdentKind Kind, - SourceLocation BLoc, SourceLocation RParenLoc, + QualType ResultTy, SourceLocation BLoc, + SourceLocation RParenLoc, DeclContext *ParentContext) - : Expr(SourceLocExprClass, getDecayedSourceLocExprType(Ctx, Kind), - VK_PRValue, OK_Ordinary), + : Expr(SourceLocExprClass, ResultTy, VK_PRValue, OK_Ordinary), BuiltinLoc(BLoc), RParenLoc(RParenLoc), ParentContext(ParentContext) { SourceLocExprBits.Kind = Kind; setDependence(ExprDependence::None); @@ -2210,6 +2162,8 @@ StringRef SourceLocExpr::getBuiltinStr() const { return "__builtin_LINE"; case Column: return "__builtin_COLUMN"; + case SourceLocStruct: + return "__builtin_source_location"; } llvm_unreachable("unexpected IdentKind!"); } @@ -2242,11 +2196,12 @@ APValue SourceLocExpr::EvaluateInContext(const ASTContext &Ctx, switch (getIdentKind()) { case SourceLocExpr::File: { SmallString<256> Path(PLoc.getFilename()); - Ctx.getLangOpts().remapPathPrefix(Path); + clang::Preprocessor::processPathForFileMacro(Path, Ctx.getLangOpts(), + Ctx.getTargetInfo()); return MakeStringLiteral(Path); } case SourceLocExpr::Function: { - const Decl *CurDecl = dyn_cast_or_null<Decl>(Context); + const auto *CurDecl = dyn_cast<Decl>(Context); return MakeStringLiteral( CurDecl ? PredefinedExpr::ComputeName(PredefinedExpr::Function, CurDecl) : std::string("")); @@ -2259,6 +2214,55 @@ APValue SourceLocExpr::EvaluateInContext(const ASTContext &Ctx, : PLoc.getColumn(); return APValue(IntVal); } + case SourceLocExpr::SourceLocStruct: { + // Fill in a std::source_location::__impl structure, by creating an + // artificial file-scoped CompoundLiteralExpr, and returning a pointer to + // that. + const CXXRecordDecl *ImplDecl = getType()->getPointeeCXXRecordDecl(); + assert(ImplDecl); + + // Construct an APValue for the __impl struct, and get or create a Decl + // corresponding to that. Note that we've already verified that the shape of + // the ImplDecl type is as expected. + + APValue Value(APValue::UninitStruct(), 0, 4); + for (FieldDecl *F : ImplDecl->fields()) { + StringRef Name = F->getName(); + if (Name == "_M_file_name") { + SmallString<256> Path(PLoc.getFilename()); + clang::Preprocessor::processPathForFileMacro(Path, Ctx.getLangOpts(), + Ctx.getTargetInfo()); + Value.getStructField(F->getFieldIndex()) = MakeStringLiteral(Path); + } else if (Name == "_M_function_name") { + // Note: this emits the PrettyFunction name -- different than what + // __builtin_FUNCTION() above returns! + const auto *CurDecl = dyn_cast<Decl>(Context); + Value.getStructField(F->getFieldIndex()) = MakeStringLiteral( + CurDecl && !isa<TranslationUnitDecl>(CurDecl) + ? StringRef(PredefinedExpr::ComputeName( + PredefinedExpr::PrettyFunction, CurDecl)) + : ""); + } else if (Name == "_M_line") { + QualType Ty = F->getType(); + llvm::APSInt IntVal(Ctx.getIntWidth(Ty), + Ty->hasUnsignedIntegerRepresentation()); + IntVal = PLoc.getLine(); + Value.getStructField(F->getFieldIndex()) = APValue(IntVal); + } else if (Name == "_M_column") { + QualType Ty = F->getType(); + llvm::APSInt IntVal(Ctx.getIntWidth(Ty), + Ty->hasUnsignedIntegerRepresentation()); + IntVal = PLoc.getColumn(); + Value.getStructField(F->getFieldIndex()) = APValue(IntVal); + } + } + + UnnamedGlobalConstantDecl *GV = + Ctx.getUnnamedGlobalConstantDecl(getType()->getPointeeType(), Value); + + return APValue(GV, CharUnits::Zero(), ArrayRef<APValue::LValuePathEntry>{}, + false); + } } llvm_unreachable("unhandled case"); } @@ -2462,8 +2466,12 @@ bool Expr::isReadIfDiscardedInCPlusPlus11() const { } // Objective-C++ extensions to the rule. - if (isa<PseudoObjectExpr>(E) || isa<ObjCIvarRefExpr>(E)) + if (isa<ObjCIvarRefExpr>(E)) return true; + if (const auto *POE = dyn_cast<PseudoObjectExpr>(E)) { + if (isa<ObjCPropertyRefExpr, ObjCSubscriptRefExpr>(POE->getSyntacticForm())) + return true; + } return false; } @@ -2713,23 +2721,35 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, } case ObjCPropertyRefExprClass: + case ObjCSubscriptRefExprClass: WarnE = this; Loc = getExprLoc(); R1 = getSourceRange(); return true; case PseudoObjectExprClass: { - const PseudoObjectExpr *PO = cast<PseudoObjectExpr>(this); + const auto *POE = cast<PseudoObjectExpr>(this); - // Only complain about things that have the form of a getter. - if (isa<UnaryOperator>(PO->getSyntacticForm()) || - isa<BinaryOperator>(PO->getSyntacticForm())) - return false; + // For some syntactic forms, we should always warn. + if (isa<ObjCPropertyRefExpr, ObjCSubscriptRefExpr>( + POE->getSyntacticForm())) { + WarnE = this; + Loc = getExprLoc(); + R1 = getSourceRange(); + return true; + } - WarnE = this; - Loc = getExprLoc(); - R1 = getSourceRange(); - return true; + // For others, we should never warn. + if (auto *BO = dyn_cast<BinaryOperator>(POE->getSyntacticForm())) + if (BO->isAssignmentOp()) + return false; + if (auto *UO = dyn_cast<UnaryOperator>(POE->getSyntacticForm())) + if (UO->isIncrementDecrementOp()) + return false; + + // Otherwise, warn if the result expression would warn. + const Expr *Result = POE->getResultExpr(); + return Result && Result->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); } case StmtExprClass: { @@ -3341,9 +3361,9 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, } bool CallExpr::isBuiltinAssumeFalse(const ASTContext &Ctx) const { - const FunctionDecl* FD = getDirectCallee(); - if (!FD || (FD->getBuiltinID() != Builtin::BI__assume && - FD->getBuiltinID() != Builtin::BI__builtin_assume)) + unsigned BuiltinID = getBuiltinCallee(); + if (BuiltinID != Builtin::BI__assume && + BuiltinID != Builtin::BI__builtin_assume) return false; const Expr* Arg = getArg(0); @@ -3352,6 +3372,10 @@ bool CallExpr::isBuiltinAssumeFalse(const ASTContext &Ctx) const { Arg->EvaluateAsBooleanCondition(ArgVal, Ctx) && !ArgVal; } +bool CallExpr::isCallToStdMove() const { + return getBuiltinCallee() == Builtin::BImove; +} + namespace { /// Look for any side effects within a Stmt. class SideEffectFinder : public ConstEvaluatedExprVisitor<SideEffectFinder> { diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index c98cfd74dab0..891105692980 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -196,7 +196,7 @@ CXXNewExpr::CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew, "Only NoInit can have no initializer!"); CXXNewExprBits.IsGlobalNew = IsGlobalNew; - CXXNewExprBits.IsArray = ArraySize.hasValue(); + CXXNewExprBits.IsArray = ArraySize.has_value(); CXXNewExprBits.ShouldPassAlignment = ShouldPassAlignment; CXXNewExprBits.UsualArrayDeleteWantsSize = UsualArrayDeleteWantsSize; CXXNewExprBits.StoredInitializationStyle = @@ -248,7 +248,7 @@ CXXNewExpr::Create(const ASTContext &Ctx, bool IsGlobalNew, InitializationStyle InitializationStyle, Expr *Initializer, QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, SourceRange DirectInitRange) { - bool IsArray = ArraySize.hasValue(); + bool IsArray = ArraySize.has_value(); bool HasInit = Initializer != nullptr; unsigned NumPlacementArgs = PlacementArgs.size(); bool IsParenTypeId = TypeIdParens.isValid(); @@ -989,7 +989,9 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr( Cons, /* Elidable=*/false, Args, HadMultipleCandidates, ListInitialization, StdInitListInitialization, ZeroInitialization, CXXConstructExpr::CK_Complete, ParenOrBraceRange), - TSI(TSI) {} + TSI(TSI) { + setDependence(computeDependence(this)); +} CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(EmptyShell Empty, unsigned NumArgs) @@ -1075,7 +1077,9 @@ CXXConstructExpr::CXXConstructExpr( TrailingArgs[I] = Args[I]; } - setDependence(computeDependence(this)); + // CXXTemporaryObjectExpr does this itself after setting its TypeSourceInfo. + if (SC == CXXConstructExprClass) + setDependence(computeDependence(this)); } CXXConstructExpr::CXXConstructExpr(StmtClass SC, EmptyShell Empty, diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp index 6998e28fd2ea..6c122cac2c60 100644 --- a/clang/lib/AST/ExprClassification.cpp +++ b/clang/lib/AST/ExprClassification.cpp @@ -465,14 +465,11 @@ static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) { islvalue = NTTParm->getType()->isReferenceType() || NTTParm->getType()->isRecordType(); else - islvalue = isa<VarDecl>(D) || isa<FieldDecl>(D) || - isa<IndirectFieldDecl>(D) || - isa<BindingDecl>(D) || - isa<MSGuidDecl>(D) || - isa<TemplateParamObjectDecl>(D) || - (Ctx.getLangOpts().CPlusPlus && - (isa<FunctionDecl>(D) || isa<MSPropertyDecl>(D) || - isa<FunctionTemplateDecl>(D))); + islvalue = + isa<VarDecl, FieldDecl, IndirectFieldDecl, BindingDecl, MSGuidDecl, + UnnamedGlobalConstantDecl, TemplateParamObjectDecl>(D) || + (Ctx.getLangOpts().CPlusPlus && + (isa<FunctionDecl, MSPropertyDecl, FunctionTemplateDecl>(D))); return islvalue ? Cl::CL_LValue : Cl::CL_PRValue; } diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 9e4088f94015..beeb775371c3 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -1978,7 +1978,8 @@ static bool IsGlobalLValue(APValue::LValueBase B) { return true; // ... the address of a function, // ... the address of a GUID [MS extension], - return isa<FunctionDecl>(D) || isa<MSGuidDecl>(D); + // ... the address of an unnamed global constant + return isa<FunctionDecl, MSGuidDecl, UnnamedGlobalConstantDecl>(D); } if (B.is<TypeInfoLValue>() || B.is<DynamicAllocLValue>()) @@ -2013,6 +2014,10 @@ static bool IsGlobalLValue(APValue::LValueBase B) { // Block variables at global or local static scope. case Expr::BlockExprClass: return !cast<BlockExpr>(E)->getBlockDecl()->hasCaptures(); + // The APValue generated from a __builtin_source_location will be emitted as a + // literal. + case Expr::SourceLocExprClass: + return true; case Expr::ImplicitValueInitExprClass: // FIXME: // We can never form an lvalue with an implicit value initialization as its @@ -2547,18 +2552,15 @@ static bool HandleFloatToIntCast(EvalInfo &Info, const Expr *E, return true; } -/// Get rounding mode used for evaluation of the specified expression. -/// \param[out] DynamicRM Is set to true is the requested rounding mode is -/// dynamic. +/// Get rounding mode to use in evaluation of the specified expression. +/// /// If rounding mode is unknown at compile time, still try to evaluate the /// expression. If the result is exact, it does not depend on rounding mode. /// So return "tonearest" mode instead of "dynamic". -static llvm::RoundingMode getActiveRoundingMode(EvalInfo &Info, const Expr *E, - bool &DynamicRM) { +static llvm::RoundingMode getActiveRoundingMode(EvalInfo &Info, const Expr *E) { llvm::RoundingMode RM = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts()).getRoundingMode(); - DynamicRM = (RM == llvm::RoundingMode::Dynamic); - if (DynamicRM) + if (RM == llvm::RoundingMode::Dynamic) RM = llvm::RoundingMode::NearestTiesToEven; return RM; } @@ -2582,14 +2584,14 @@ static bool checkFloatingPointResult(EvalInfo &Info, const Expr *E, if ((St != APFloat::opOK) && (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic || - FPO.getFPExceptionMode() != LangOptions::FPE_Ignore || + FPO.getExceptionMode() != LangOptions::FPE_Ignore || FPO.getAllowFEnvAccess())) { Info.FFDiag(E, diag::note_constexpr_float_arithmetic_strict); return false; } if ((St & APFloat::opStatus::opInvalidOp) && - FPO.getFPExceptionMode() != LangOptions::FPE_Ignore) { + FPO.getExceptionMode() != LangOptions::FPE_Ignore) { // There is no usefully definable result. Info.FFDiag(E); return false; @@ -2608,8 +2610,7 @@ static bool HandleFloatToFloatCast(EvalInfo &Info, const Expr *E, QualType SrcType, QualType DestType, APFloat &Result) { assert(isa<CastExpr>(E) || isa<CompoundAssignOperator>(E)); - bool DynamicRM; - llvm::RoundingMode RM = getActiveRoundingMode(Info, E, DynamicRM); + llvm::RoundingMode RM = getActiveRoundingMode(Info, E); APFloat::opStatus St; APFloat Value = Result; bool ignored; @@ -2844,8 +2845,7 @@ static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS, static bool handleFloatFloatBinOp(EvalInfo &Info, const BinaryOperator *E, APFloat &LHS, BinaryOperatorKind Opcode, const APFloat &RHS) { - bool DynamicRM; - llvm::RoundingMode RM = getActiveRoundingMode(Info, E, DynamicRM); + llvm::RoundingMode RM = getActiveRoundingMode(Info, E); APFloat::opStatus St; switch (Opcode) { default: @@ -4024,6 +4024,16 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, return CompleteObject(LVal.Base, &V, GD->getType()); } + // Allow reading the APValue from an UnnamedGlobalConstantDecl. + if (auto *GCD = dyn_cast<UnnamedGlobalConstantDecl>(D)) { + if (isModification(AK)) { + Info.FFDiag(E, diag::note_constexpr_modify_global); + return CompleteObject(); + } + return CompleteObject(LVal.Base, const_cast<APValue *>(&GCD->getValue()), + GCD->getType()); + } + // Allow reading from template parameter objects. if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(D)) { if (isModification(AK)) { @@ -4244,9 +4254,33 @@ handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, QualType Type, Info.FFDiag(Conv); return false; } + APValue Lit; if (!Evaluate(Lit, Info, CLE->getInitializer())) return false; + + // According to GCC info page: + // + // 6.28 Compound Literals + // + // As an optimization, G++ sometimes gives array compound literals longer + // lifetimes: when the array either appears outside a function or has a + // const-qualified type. If foo and its initializer had elements of type + // char *const rather than char *, or if foo were a global variable, the + // array would have static storage duration. But it is probably safest + // just to avoid the use of array compound literals in C++ code. + // + // Obey that rule by checking constness for converted array types. + + QualType CLETy = CLE->getType(); + if (CLETy->isArrayType() && !Type->isArrayType()) { + if (!CLETy.isConstant(Info.Ctx)) { + Info.FFDiag(Conv); + Info.Note(CLE->getExprLoc(), diag::note_declared_at); + return false; + } + } + CompleteObject LitObj(LVal.Base, &Lit, Base->getType()); return extractSubobject(Info, Conv, LitObj, LVal.Designator, RVal, AK); } else if (isa<StringLiteral>(Base) || isa<PredefinedExpr>(Base)) { @@ -5003,6 +5037,18 @@ static EvalStmtResult EvaluateSwitch(StmtResult &Result, EvalInfo &Info, llvm_unreachable("Invalid EvalStmtResult!"); } +static bool CheckLocalVariableDeclaration(EvalInfo &Info, const VarDecl *VD) { + // An expression E is a core constant expression unless the evaluation of E + // would evaluate one of the following: [C++2b] - a control flow that passes + // through a declaration of a variable with static or thread storage duration. + if (VD->isLocalVarDecl() && VD->isStaticLocal()) { + Info.CCEDiag(VD->getLocation(), diag::note_constexpr_static_local) + << (VD->getTSCSpec() == TSCS_unspecified ? 0 : 1) << VD; + return false; + } + return true; +} + // Evaluate a statement. static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, const Stmt *S, const SwitchCase *Case) { @@ -5113,6 +5159,8 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, const DeclStmt *DS = cast<DeclStmt>(S); for (const auto *D : DS->decls()) { if (const auto *VD = dyn_cast<VarDecl>(D)) { + if (!CheckLocalVariableDeclaration(Info, VD)) + return ESR_Failed; if (VD->hasLocalStorage() && !VD->getInit()) if (!EvaluateVarDecl(Info, VD)) return ESR_Failed; @@ -5156,6 +5204,9 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, case Stmt::DeclStmtClass: { const DeclStmt *DS = cast<DeclStmt>(S); for (const auto *D : DS->decls()) { + const VarDecl *VD = dyn_cast_or_null<VarDecl>(D); + if (VD && !CheckLocalVariableDeclaration(Info, VD)) + return ESR_Failed; // Each declaration initialization is its own full-expression. FullExpressionRAII Scope(Info); if (!EvaluateDecl(Info, D) && !Info.noteFailure()) @@ -6124,9 +6175,6 @@ static bool HandleFunctionCall(SourceLocation CallLoc, if (!handleTrivialCopy(Info, MD->getParamDecl(0), Args[0], RHSValue, MD->getParent()->isUnion())) return false; - if (Info.getLangOpts().CPlusPlus20 && MD->isTrivial() && - !HandleUnionActiveMemberChange(Info, Args[0], *This)) - return false; if (!handleAssignment(Info, Args[0], *This, MD->getThisType(), RHSValue)) return false; @@ -6507,7 +6555,7 @@ static bool HandleDestructionImpl(EvalInfo &Info, SourceLocation CallLoc, // We don't have a good way to iterate fields in reverse, so collect all the // fields first and then walk them backwards. - SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end()); + SmallVector<FieldDecl*, 16> Fields(RD->fields()); for (const FieldDecl *FD : llvm::reverse(Fields)) { if (FD->isUnnamedBitfield()) continue; @@ -7638,6 +7686,15 @@ public: if (!EvaluateObjectArgument(Info, Args[0], ThisVal)) return false; This = &ThisVal; + + // If this is syntactically a simple assignment using a trivial + // assignment operator, start the lifetimes of union members as needed, + // per C++20 [class.union]5. + if (Info.getLangOpts().CPlusPlus20 && OCE && + OCE->getOperator() == OO_Equal && MD->isTrivial() && + !HandleUnionActiveMemberChange(Info, Args[0], ThisVal)) + return false; + Args = Args.slice(1); } else if (MD && MD->isLambdaStaticInvoker()) { // Map the static invoker for the lambda back to the call operator. @@ -8089,6 +8146,7 @@ public: bool VisitVarDecl(const Expr *E, const VarDecl *VD); bool VisitUnaryPreIncDec(const UnaryOperator *UO); + bool VisitCallExpr(const CallExpr *E); bool VisitDeclRefExpr(const DeclRefExpr *E); bool VisitPredefinedExpr(const PredefinedExpr *E) { return Success(E); } bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E); @@ -8152,7 +8210,8 @@ static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info, bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { const NamedDecl *D = E->getDecl(); - if (isa<FunctionDecl, MSGuidDecl, TemplateParamObjectDecl>(D)) + if (isa<FunctionDecl, MSGuidDecl, TemplateParamObjectDecl, + UnnamedGlobalConstantDecl>(D)) return Success(cast<ValueDecl>(D)); if (const VarDecl *VD = dyn_cast<VarDecl>(D)) return VisitVarDecl(E, VD); @@ -8253,6 +8312,20 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { return Success(*V, E); } +bool LValueExprEvaluator::VisitCallExpr(const CallExpr *E) { + switch (E->getBuiltinCallee()) { + case Builtin::BIas_const: + case Builtin::BIforward: + case Builtin::BImove: + case Builtin::BImove_if_noexcept: + if (cast<FunctionDecl>(E->getCalleeDecl())->isConstexpr()) + return Visit(E->getArg(0)); + break; + } + + return ExprEvaluatorBaseTy::VisitCallExpr(E); +} + bool LValueExprEvaluator::VisitMaterializeTemporaryExpr( const MaterializeTemporaryExpr *E) { // Walk through the expression to find the materialized temporary itself. @@ -8384,7 +8457,8 @@ bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) { bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { // FIXME: Deal with vectors as array subscript bases. - if (E->getBase()->getType()->isVectorType()) + if (E->getBase()->getType()->isVectorType() || + E->getBase()->getType()->isVLSTBuiltinType()) return Error(E); APSInt Index; @@ -8517,7 +8591,7 @@ static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx, Into = ExprResult.Val.getInt(); if (Into.isNegative() || !Into.isIntN(BitsInSizeT)) return false; - Into = Into.zextOrSelf(BitsInSizeT); + Into = Into.zext(BitsInSizeT); return true; }; @@ -8576,7 +8650,7 @@ static bool evaluateLValueAsAllocSize(EvalInfo &Info, APValue::LValueBase Base, return false; const Expr *Init = VD->getAnyInitializer(); - if (!Init) + if (!Init || Init->getType().isNull()) return false; const Expr *E = Init->IgnoreParens(); @@ -8692,7 +8766,7 @@ public: bool VisitCXXNewExpr(const CXXNewExpr *E); bool VisitSourceLocExpr(const SourceLocExpr *E) { - assert(E->isStringType() && "SourceLocExpr isn't a pointer type?"); + assert(!E->isIntType() && "SourceLocExpr isn't a pointer type?"); APValue LValResult = E->EvaluateInContext( Info.Ctx, Info.CurrentCall->CurSourceLocExprScope.getDefaultExpr()); Result.setFrom(Info.Ctx, LValResult); @@ -8709,7 +8783,7 @@ public: ArrayType::Normal, 0); StringLiteral *SL = - StringLiteral::Create(Info.Ctx, ResultStr, StringLiteral::Ascii, + StringLiteral::Create(Info.Ctx, ResultStr, StringLiteral::Ordinary, /*Pascal*/ false, ArrayTy, E->getLocation()); evaluateLValue(SL, Result); @@ -8757,6 +8831,22 @@ bool PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) { return evaluateLValue(E->getSubExpr(), Result); } +// Is the provided decl 'std::source_location::current'? +static bool IsDeclSourceLocationCurrent(const FunctionDecl *FD) { + if (!FD) + return false; + const IdentifierInfo *FnII = FD->getIdentifier(); + if (!FnII || !FnII->isStr("current")) + return false; + + const auto *RD = dyn_cast<RecordDecl>(FD->getParent()); + if (!RD) + return false; + + const IdentifierInfo *ClassII = RD->getIdentifier(); + return RD->isInStdNamespace() && ClassII && ClassII->isStr("source_location"); +} + bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) { const Expr *SubExpr = E->getSubExpr(); @@ -8774,14 +8864,24 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) { // permitted in constant expressions in C++11. Bitcasts from cv void* are // also static_casts, but we disallow them as a resolution to DR1312. if (!E->getType()->isVoidPointerType()) { - if (!Result.InvalidBase && !Result.Designator.Invalid && + // In some circumstances, we permit casting from void* to cv1 T*, when the + // actual pointee object is actually a cv2 T. + bool VoidPtrCastMaybeOK = + !Result.InvalidBase && !Result.Designator.Invalid && !Result.IsNullPtr && Info.Ctx.hasSameUnqualifiedType(Result.Designator.getType(Info.Ctx), - E->getType()->getPointeeType()) && - Info.getStdAllocatorCaller("allocate")) { - // Inside a call to std::allocator::allocate and friends, we permit - // casting from void* back to cv1 T* for a pointer that points to a - // cv2 T. + E->getType()->getPointeeType()); + // 1. We'll allow it in std::allocator::allocate, and anything which that + // calls. + // 2. HACK 2022-03-28: Work around an issue with libstdc++'s + // <source_location> header. Fixed in GCC 12 and later (2022-04-??). + // We'll allow it in the body of std::source_location::current. GCC's + // implementation had a parameter of type `void*`, and casts from + // that back to `const __impl*` in its body. + if (VoidPtrCastMaybeOK && + (Info.getStdAllocatorCaller("allocate") || + IsDeclSourceLocationCurrent(Info.CurrentCall->Callee))) { + // Permitted. } else { Result.Designator.setInvalid(); if (SubExpr->getType()->isVoidPointerType()) @@ -9004,6 +9104,8 @@ static bool isOneByteCharacterType(QualType T) { bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp) { switch (BuiltinOp) { + case Builtin::BIaddressof: + case Builtin::BI__addressof: case Builtin::BI__builtin_addressof: return evaluateLValue(E->getArg(0), Result); case Builtin::BI__builtin_assume_aligned: { @@ -9421,7 +9523,7 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { bool ValueInit = false; QualType AllocType = E->getAllocatedType(); - if (Optional<const Expr*> ArraySize = E->getArraySize()) { + if (Optional<const Expr *> ArraySize = E->getArraySize()) { const Expr *Stripped = *ArraySize; for (; auto *ICE = dyn_cast<ImplicitCastExpr>(Stripped); Stripped = ICE->getSubExpr()) @@ -9475,8 +9577,8 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { unsigned Bits = std::max(CAT->getSize().getBitWidth(), ArrayBound.getBitWidth()); - llvm::APInt InitBound = CAT->getSize().zextOrSelf(Bits); - llvm::APInt AllocBound = ArrayBound.zextOrSelf(Bits); + llvm::APInt InitBound = CAT->getSize().zext(Bits); + llvm::APInt AllocBound = ArrayBound.zext(Bits); if (InitBound.ugt(AllocBound)) { if (IsNothrow) return ZeroInitialization(E); @@ -9914,6 +10016,17 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { ImplicitValueInitExpr VIE(HaveInit ? Info.Ctx.IntTy : Field->getType()); const Expr *Init = HaveInit ? E->getInit(ElementNo++) : &VIE; + if (Field->getType()->isIncompleteArrayType()) { + if (auto *CAT = Info.Ctx.getAsConstantArrayType(Init->getType())) { + if (!CAT->getSize().isZero()) { + // Bail out for now. This might sort of "work", but the rest of the + // code isn't really prepared to handle it. + Info.FFDiag(Init, diag::note_constexpr_unsupported_flexible_array); + return false; + } + } + } + // Temporarily override This, in case there's a CXXDefaultInitExpr in here. ThisOverrideRAII ThisOverride(*Info.CurrentCall, &This, isa<CXXDefaultInitExpr>(Init)); @@ -10079,7 +10192,6 @@ bool RecordExprEvaluator::VisitLambdaExpr(const LambdaExpr *E) { // Iterate through all the lambda's closure object's fields and initialize // them. auto *CaptureInitIt = E->capture_init_begin(); - const LambdaCapture *CaptureIt = ClosureClass->captures_begin(); bool Success = true; const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(ClosureClass); for (const auto *Field : ClosureClass->fields()) { @@ -10103,7 +10215,6 @@ bool RecordExprEvaluator::VisitLambdaExpr(const LambdaExpr *E) { return false; Success = false; } - ++CaptureIt; } return Success; } @@ -10261,9 +10372,9 @@ bool VectorExprEvaluator::VisitCastExpr(const CastExpr *E) { for (unsigned i = 0; i < NElts; i++) { llvm::APInt Elt; if (BigEndian) - Elt = SValInt.rotl(i*EltSize+FloatEltSize).trunc(FloatEltSize); + Elt = SValInt.rotl(i * EltSize + FloatEltSize).trunc(FloatEltSize); else - Elt = SValInt.rotr(i*EltSize).trunc(FloatEltSize); + Elt = SValInt.rotr(i * EltSize).trunc(FloatEltSize); Elts.push_back(APValue(APFloat(Sem, Elt))); } } else if (EltTy->isIntegerType()) { @@ -13764,10 +13875,12 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BI__builtin_huge_val: case Builtin::BI__builtin_huge_valf: case Builtin::BI__builtin_huge_vall: + case Builtin::BI__builtin_huge_valf16: case Builtin::BI__builtin_huge_valf128: case Builtin::BI__builtin_inf: case Builtin::BI__builtin_inff: case Builtin::BI__builtin_infl: + case Builtin::BI__builtin_inff16: case Builtin::BI__builtin_inff128: { const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(E->getType()); @@ -13778,6 +13891,7 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BI__builtin_nans: case Builtin::BI__builtin_nansf: case Builtin::BI__builtin_nansl: + case Builtin::BI__builtin_nansf16: case Builtin::BI__builtin_nansf128: if (!TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0), true, Result)) @@ -13787,6 +13901,7 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BI__builtin_nan: case Builtin::BI__builtin_nanf: case Builtin::BI__builtin_nanl: + case Builtin::BI__builtin_nanf16: case Builtin::BI__builtin_nanf128: // If this is __builtin_nan() turn this into a nan, otherwise we // can't constant fold it. diff --git a/clang/lib/AST/FormatString.cpp b/clang/lib/AST/FormatString.cpp index 102bcca96a38..4977aaa51319 100644 --- a/clang/lib/AST/FormatString.cpp +++ b/clang/lib/AST/FormatString.cpp @@ -760,7 +760,7 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target, return true; case ConversionSpecifier::FreeBSDrArg: case ConversionSpecifier::FreeBSDyArg: - return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4(); + return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS(); default: return false; } @@ -795,7 +795,7 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target, return true; case ConversionSpecifier::FreeBSDrArg: case ConversionSpecifier::FreeBSDyArg: - return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4(); + return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS(); default: return false; } diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 124a6ff03f18..82aa413dabbc 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -284,7 +284,7 @@ public: ~LocalScope() override { this->emitDestruction(); } void addLocal(const Scope::Local &Local) override { - if (!Idx.hasValue()) { + if (!Idx) { Idx = this->Ctx->Descriptors.size(); this->Ctx->Descriptors.emplace_back(); } @@ -293,7 +293,7 @@ public: } void emitDestruction() override { - if (!Idx.hasValue()) + if (!Idx) return; this->Ctx->emitDestroy(*Idx, SourceInfo{}); } diff --git a/clang/lib/AST/Interp/Function.cpp b/clang/lib/AST/Interp/Function.cpp index 0ed13a92aa38..6ba97df1cd30 100644 --- a/clang/lib/AST/Interp/Function.cpp +++ b/clang/lib/AST/Interp/Function.cpp @@ -34,8 +34,7 @@ Function::ParamDescriptor Function::getParamDescriptor(unsigned Offset) const { SourceInfo Function::getSource(CodePtr PC) const { unsigned Offset = PC - getCodeBegin(); using Elem = std::pair<unsigned, SourceInfo>; - auto It = std::lower_bound(SrcMap.begin(), SrcMap.end(), Elem{Offset, {}}, - [](Elem A, Elem B) { return A.first < B.first; }); + auto It = llvm::lower_bound(SrcMap, Elem{Offset, {}}, llvm::less_first()); if (It == SrcMap.end() || It->first != Offset) llvm::report_fatal_error("missing source location"); return It->second; diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 2e734e2b28cd..91f41778ee68 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -40,65 +40,10 @@ using namespace clang; namespace { -/// Retrieve the declaration context that should be used when mangling the given -/// declaration. -static const DeclContext *getEffectiveDeclContext(const Decl *D) { - // The ABI assumes that lambda closure types that occur within - // default arguments live in the context of the function. However, due to - // the way in which Clang parses and creates function declarations, this is - // 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(); - } - - // Perform the same check for block literals. - if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { - if (ParmVarDecl *ContextParam - = dyn_cast_or_null<ParmVarDecl>(BD->getBlockManglingContextDecl())) - return ContextParam->getDeclContext(); - } - - const DeclContext *DC = D->getDeclContext(); - if (isa<CapturedDecl>(DC) || isa<OMPDeclareReductionDecl>(DC) || - isa<OMPDeclareMapperDecl>(DC)) { - return getEffectiveDeclContext(cast<Decl>(DC)); - } - - if (const auto *VD = dyn_cast<VarDecl>(D)) - if (VD->isExternC()) - return VD->getASTContext().getTranslationUnitDecl(); - - if (const auto *FD = dyn_cast<FunctionDecl>(D)) - if (FD->isExternC()) - return FD->getASTContext().getTranslationUnitDecl(); - - return DC->getRedeclContext(); -} - -static const DeclContext *getEffectiveParentContext(const DeclContext *DC) { - return getEffectiveDeclContext(cast<Decl>(DC)); -} - static bool isLocalContainerContext(const DeclContext *DC) { return isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC) || isa<BlockDecl>(DC); } -static const RecordDecl *GetLocalClassDecl(const Decl *D) { - const DeclContext *DC = getEffectiveDeclContext(D); - while (!DC->isNamespace() && !DC->isTranslationUnit()) { - if (isLocalContainerContext(DC)) - return dyn_cast<RecordDecl>(D); - D = cast<Decl>(DC); - DC = getEffectiveDeclContext(D); - } - return nullptr; -} - static const FunctionDecl *getStructor(const FunctionDecl *fn) { if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate()) return ftd->getTemplatedDecl(); @@ -126,14 +71,15 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext { llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator; llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier; const DiscriminatorOverrideTy DiscriminatorOverride = nullptr; + NamespaceDecl *StdNamespace = nullptr; bool NeedsUniqueInternalLinkageNames = false; public: explicit ItaniumMangleContextImpl( ASTContext &Context, DiagnosticsEngine &Diags, - DiscriminatorOverrideTy DiscriminatorOverride) - : ItaniumMangleContext(Context, Diags), + DiscriminatorOverrideTy DiscriminatorOverride, bool IsAux = false) + : ItaniumMangleContext(Context, Diags, IsAux), DiscriminatorOverride(DiscriminatorOverride) {} /// @name Mangler Entry Points @@ -184,6 +130,8 @@ public: void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) override; + void mangleModuleInitializer(const Module *Module, raw_ostream &) override; + bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) { // Lambda closure types are already numbered. if (isLambda(ND)) @@ -197,7 +145,7 @@ public: // Use the canonical number for externally visible decls. if (ND->isExternallyVisible()) { - unsigned discriminator = getASTContext().getManglingNumber(ND); + unsigned discriminator = getASTContext().getManglingNumber(ND, isAux()); if (discriminator == 1) return false; disc = discriminator - 2; @@ -249,6 +197,16 @@ public: return DiscriminatorOverride; } + NamespaceDecl *getStdNamespace(); + + const DeclContext *getEffectiveDeclContext(const Decl *D); + const DeclContext *getEffectiveParentContext(const DeclContext *DC) { + return getEffectiveDeclContext(cast<Decl>(DC)); + } + + bool isInternalLinkageDecl(const NamedDecl *ND); + const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC); + /// @} }; @@ -267,10 +225,10 @@ class CXXNameMangler { /// that's not a template specialization; otherwise it's the pattern /// for that specialization. const NamedDecl *Structor; - unsigned StructorType; + unsigned StructorType = 0; /// The next substitution sequence number. - unsigned SeqID; + unsigned SeqID = 0; class FunctionTypeDepthState { unsigned Bits; @@ -427,35 +385,44 @@ class CXXNameMangler { ASTContext &getASTContext() const { return Context.getASTContext(); } + bool isStd(const NamespaceDecl *NS); + bool isStdNamespace(const DeclContext *DC); + + const RecordDecl *GetLocalClassDecl(const Decl *D); + const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC); + bool isSpecializedAs(QualType S, llvm::StringRef Name, QualType A); + bool isStdCharSpecialization(const ClassTemplateSpecializationDecl *SD, + llvm::StringRef Name, bool HasAllocator); + public: CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_, const NamedDecl *D = nullptr, bool NullOut_ = false) - : Context(C), Out(Out_), NullOut(NullOut_), Structor(getStructor(D)), - StructorType(0), SeqID(0), AbiTagsRoot(AbiTags) { + : Context(C), Out(Out_), NullOut(NullOut_), Structor(getStructor(D)), + AbiTagsRoot(AbiTags) { // These can't be mangled without a ctor type or dtor type. assert(!D || (!isa<CXXDestructorDecl>(D) && !isa<CXXConstructorDecl>(D))); } CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_, const CXXConstructorDecl *D, CXXCtorType Type) - : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), - SeqID(0), AbiTagsRoot(AbiTags) { } + : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), + AbiTagsRoot(AbiTags) {} CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_, const CXXDestructorDecl *D, CXXDtorType Type) - : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), - SeqID(0), AbiTagsRoot(AbiTags) { } + : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), + AbiTagsRoot(AbiTags) {} CXXNameMangler(CXXNameMangler &Outer, raw_ostream &Out_) - : Context(Outer.Context), Out(Out_), NullOut(false), - Structor(Outer.Structor), StructorType(Outer.StructorType), - SeqID(Outer.SeqID), FunctionTypeDepth(Outer.FunctionTypeDepth), - AbiTagsRoot(AbiTags), Substitutions(Outer.Substitutions) {} + : Context(Outer.Context), Out(Out_), Structor(Outer.Structor), + StructorType(Outer.StructorType), SeqID(Outer.SeqID), + FunctionTypeDepth(Outer.FunctionTypeDepth), AbiTagsRoot(AbiTags), + Substitutions(Outer.Substitutions), + ModuleSubstitutions(Outer.ModuleSubstitutions) {} CXXNameMangler(CXXNameMangler &Outer, llvm::raw_null_ostream &Out_) - : Context(Outer.Context), Out(Out_), NullOut(true), - Structor(Outer.Structor), StructorType(Outer.StructorType), - SeqID(Outer.SeqID), FunctionTypeDepth(Outer.FunctionTypeDepth), - AbiTagsRoot(AbiTags), Substitutions(Outer.Substitutions) {} + : CXXNameMangler(Outer, (raw_ostream &)Out_) { + NullOut = true; + } raw_ostream &getStream() { return Out; } @@ -473,10 +440,12 @@ public: void mangleType(QualType T); void mangleNameOrStandardSubstitution(const NamedDecl *ND); void mangleLambdaSig(const CXXRecordDecl *Lambda); + void mangleModuleNamePrefix(StringRef Name, bool IsPartition = false); private: bool mangleSubstitution(const NamedDecl *ND); + bool mangleSubstitution(NestedNameSpecifier *NNS); bool mangleSubstitution(QualType T); bool mangleSubstitution(TemplateName Template); bool mangleSubstitution(uintptr_t Ptr); @@ -490,6 +459,11 @@ private: addSubstitution(reinterpret_cast<uintptr_t>(ND)); } + void addSubstitution(NestedNameSpecifier *NNS) { + NNS = Context.getASTContext().getCanonicalNestedNameSpecifier(NNS); + + addSubstitution(reinterpret_cast<uintptr_t>(NNS)); + } void addSubstitution(QualType T); void addSubstitution(TemplateName Template); void addSubstitution(uintptr_t Ptr); @@ -508,22 +482,21 @@ private: void mangleNameWithAbiTags(GlobalDecl GD, const AbiTagList *AdditionalAbiTags); - void mangleModuleName(const Module *M); - void mangleModuleNamePrefix(StringRef Name); + void mangleModuleName(const NamedDecl *ND); void mangleTemplateName(const TemplateDecl *TD, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs); - void mangleUnqualifiedName(GlobalDecl GD, + void mangleUnqualifiedName(GlobalDecl GD, const DeclContext *DC, const AbiTagList *AdditionalAbiTags) { - mangleUnqualifiedName(GD, cast<NamedDecl>(GD.getDecl())->getDeclName(), UnknownArity, - AdditionalAbiTags); + mangleUnqualifiedName(GD, cast<NamedDecl>(GD.getDecl())->getDeclName(), DC, + UnknownArity, AdditionalAbiTags); } void mangleUnqualifiedName(GlobalDecl GD, DeclarationName Name, - unsigned KnownArity, + const DeclContext *DC, unsigned KnownArity, const AbiTagList *AdditionalAbiTags); - void mangleUnscopedName(GlobalDecl GD, + void mangleUnscopedName(GlobalDecl GD, const DeclContext *DC, const AbiTagList *AdditionalAbiTags); - void mangleUnscopedTemplateName(GlobalDecl GD, + void mangleUnscopedTemplateName(GlobalDecl GD, const DeclContext *DC, const AbiTagList *AdditionalAbiTags); void mangleSourceName(const IdentifierInfo *II); void mangleRegCallName(const IdentifierInfo *II); @@ -628,7 +601,71 @@ private: } -static bool isInternalLinkageDecl(const NamedDecl *ND) { +NamespaceDecl *ItaniumMangleContextImpl::getStdNamespace() { + if (!StdNamespace) { + StdNamespace = NamespaceDecl::Create( + getASTContext(), getASTContext().getTranslationUnitDecl(), + /*Inline*/ false, SourceLocation(), SourceLocation(), + &getASTContext().Idents.get("std"), + /*PrevDecl*/ nullptr); + StdNamespace->setImplicit(); + } + return StdNamespace; +} + +/// Retrieve the declaration context that should be used when mangling the given +/// declaration. +const DeclContext * +ItaniumMangleContextImpl::getEffectiveDeclContext(const Decl *D) { + // The ABI assumes that lambda closure types that occur within + // default arguments live in the context of the function. However, due to + // the way in which Clang parses and creates function declarations, this is + // 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(); + } + + // Perform the same check for block literals. + if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { + if (ParmVarDecl *ContextParam = + dyn_cast_or_null<ParmVarDecl>(BD->getBlockManglingContextDecl())) + return ContextParam->getDeclContext(); + } + + // On ARM and AArch64, the va_list tag is always mangled as if in the std + // namespace. We do not represent va_list as actually being in the std + // namespace in C because this would result in incorrect debug info in C, + // among other things. It is important for both languages to have the same + // mangling in order for -fsanitize=cfi-icall to work. + if (D == getASTContext().getVaListTagDecl()) { + const llvm::Triple &T = getASTContext().getTargetInfo().getTriple(); + if (T.isARM() || T.isThumb() || T.isAArch64()) + return getStdNamespace(); + } + + const DeclContext *DC = D->getDeclContext(); + if (isa<CapturedDecl>(DC) || isa<OMPDeclareReductionDecl>(DC) || + isa<OMPDeclareMapperDecl>(DC)) { + return getEffectiveDeclContext(cast<Decl>(DC)); + } + + if (const auto *VD = dyn_cast<VarDecl>(D)) + if (VD->isExternC()) + return getASTContext().getTranslationUnitDecl(); + + if (const auto *FD = dyn_cast<FunctionDecl>(D)) + if (FD->isExternC()) + return getASTContext().getTranslationUnitDecl(); + + return DC->getRedeclContext(); +} + +bool ItaniumMangleContextImpl::isInternalLinkageDecl(const NamedDecl *ND) { if (ND && ND->getFormalLinkage() == InternalLinkage && !ND->isExternallyVisible() && getEffectiveDeclContext(ND)->isFileContext() && @@ -704,7 +741,8 @@ bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { if (VD->isExternC()) return false; - // Variables at global scope with non-internal linkage are not mangled. + // Variables at global scope are not mangled unless they have internal + // linkage or are specializations or are attached to a named module. const DeclContext *DC = getEffectiveDeclContext(D); // Check for extern variable declared locally. if (DC->isFunctionOrMethod() && D->hasLinkage()) @@ -712,7 +750,8 @@ bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { DC = getEffectiveParentContext(DC); if (DC->isTranslationUnit() && D->getFormalLinkage() != InternalLinkage && !CXXNameMangler::shouldHaveAbiTags(*this, VD) && - !isa<VarTemplateSpecializationDecl>(VD)) + !isa<VarTemplateSpecializationDecl>(VD) && + !VD->getOwningModuleForLinkage()) return false; } @@ -862,18 +901,9 @@ void CXXNameMangler::mangleFunctionEncodingBareType(const FunctionDecl *FD) { MangleReturnType, FD); } -static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) { - while (isa<LinkageSpecDecl>(DC)) { - DC = getEffectiveParentContext(DC); - } - - return DC; -} - /// Return whether a given namespace is the 'std' namespace. -static bool isStd(const NamespaceDecl *NS) { - if (!IgnoreLinkageSpecDecls(getEffectiveParentContext(NS)) - ->isTranslationUnit()) +bool CXXNameMangler::isStd(const NamespaceDecl *NS) { + if (!Context.getEffectiveParentContext(NS)->isTranslationUnit()) return false; const IdentifierInfo *II = NS->getOriginalNamespace()->getIdentifier(); @@ -882,7 +912,7 @@ static bool isStd(const NamespaceDecl *NS) { // isStdNamespace - Return whether a given decl context is a toplevel 'std' // namespace. -static bool isStdNamespace(const DeclContext *DC) { +bool CXXNameMangler::isStdNamespace(const DeclContext *DC) { if (!DC->isNamespace()) return false; @@ -956,6 +986,17 @@ void CXXNameMangler::mangleName(GlobalDecl GD) { } } +const RecordDecl *CXXNameMangler::GetLocalClassDecl(const Decl *D) { + const DeclContext *DC = Context.getEffectiveDeclContext(D); + while (!DC->isNamespace() && !DC->isTranslationUnit()) { + if (isLocalContainerContext(DC)) + return dyn_cast<RecordDecl>(D); + D = cast<Decl>(DC); + DC = Context.getEffectiveDeclContext(D); + } + return nullptr; +} + void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD, const AbiTagList *AdditionalAbiTags) { const NamedDecl *ND = cast<NamedDecl>(GD.getDecl()); @@ -964,7 +1005,7 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD, // ::= [<module-name>] <unscoped-template-name> <template-args> // ::= <local-name> // - const DeclContext *DC = getEffectiveDeclContext(ND); + const DeclContext *DC = Context.getEffectiveDeclContext(ND); // If this is an extern variable declared locally, the relevant DeclContext // is that of the containing namespace, or the translation unit. @@ -972,27 +1013,19 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD, // a proper semantic declaration context! if (isLocalContainerContext(DC) && ND->hasLinkage() && !isLambda(ND)) while (!DC->isNamespace() && !DC->isTranslationUnit()) - DC = getEffectiveParentContext(DC); + DC = Context.getEffectiveParentContext(DC); else if (GetLocalClassDecl(ND)) { mangleLocalName(GD, AdditionalAbiTags); return; } - DC = IgnoreLinkageSpecDecls(DC); + assert(!isa<LinkageSpecDecl>(DC) && "context cannot be LinkageSpecDecl"); if (isLocalContainerContext(DC)) { mangleLocalName(GD, AdditionalAbiTags); return; } - // Do not mangle the owning module for an external linkage declaration. - // This enables backwards-compatibility with non-modular code, and is - // a valid choice since conflicts are not permitted by C++ Modules TS - // [basic.def.odr]/6.2. - if (!ND->hasExternalFormalLinkage()) - if (Module *M = ND->getOwningModuleForLinkage()) - mangleModuleName(M); - // Closures can require a nested-name mangling even if they're semantically // in the global namespace. if (const NamedDecl *PrefixND = getClosurePrefix(ND)) { @@ -1004,38 +1037,35 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD, // Check if we have a template. const TemplateArgumentList *TemplateArgs = nullptr; if (GlobalDecl TD = isTemplate(GD, TemplateArgs)) { - mangleUnscopedTemplateName(TD, AdditionalAbiTags); + mangleUnscopedTemplateName(TD, DC, AdditionalAbiTags); mangleTemplateArgs(asTemplateName(TD), *TemplateArgs); return; } - mangleUnscopedName(GD, AdditionalAbiTags); + mangleUnscopedName(GD, DC, AdditionalAbiTags); return; } mangleNestedName(GD, DC, AdditionalAbiTags); } -void CXXNameMangler::mangleModuleName(const Module *M) { - // Implement the C++ Modules TS name mangling proposal; see - // https://gcc.gnu.org/wiki/cxx-modules?action=AttachFile - // - // <module-name> ::= W <unscoped-name>+ E - // ::= W <module-subst> <unscoped-name>* E - Out << 'W'; - mangleModuleNamePrefix(M->Name); - Out << 'E'; +void CXXNameMangler::mangleModuleName(const NamedDecl *ND) { + if (ND->isExternallyVisible()) + if (Module *M = ND->getOwningModuleForLinkage()) + mangleModuleNamePrefix(M->getPrimaryModuleInterfaceName()); } -void CXXNameMangler::mangleModuleNamePrefix(StringRef Name) { - // <module-subst> ::= _ <seq-id> # 0 < seq-id < 10 - // ::= W <seq-id - 10> _ # otherwise +// <module-name> ::= <module-subname> +// ::= <module-name> <module-subname> +// ::= <substitution> +// <module-subname> ::= W <source-name> +// ::= W P <source-name> +void CXXNameMangler::mangleModuleNamePrefix(StringRef Name, bool IsPartition) { + // <substitution> ::= S <seq-id> _ auto It = ModuleSubstitutions.find(Name); if (It != ModuleSubstitutions.end()) { - if (It->second < 10) - Out << '_' << static_cast<char>('0' + It->second); - else - Out << 'W' << (It->second - 10) << '_'; + Out << 'S'; + mangleSeqID(It->second); return; } @@ -1044,40 +1074,45 @@ void CXXNameMangler::mangleModuleNamePrefix(StringRef Name) { auto Parts = Name.rsplit('.'); if (Parts.second.empty()) Parts.second = Parts.first; - else - mangleModuleNamePrefix(Parts.first); + else { + mangleModuleNamePrefix(Parts.first, IsPartition); + IsPartition = false; + } + Out << 'W'; + if (IsPartition) + Out << 'P'; Out << Parts.second.size() << Parts.second; - ModuleSubstitutions.insert({Name, ModuleSubstitutions.size()}); + ModuleSubstitutions.insert({Name, SeqID++}); } void CXXNameMangler::mangleTemplateName(const TemplateDecl *TD, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs) { - const DeclContext *DC = IgnoreLinkageSpecDecls(getEffectiveDeclContext(TD)); + const DeclContext *DC = Context.getEffectiveDeclContext(TD); if (DC->isTranslationUnit() || isStdNamespace(DC)) { - mangleUnscopedTemplateName(TD, nullptr); + mangleUnscopedTemplateName(TD, DC, nullptr); mangleTemplateArgs(asTemplateName(TD), TemplateArgs, NumTemplateArgs); } else { mangleNestedName(TD, TemplateArgs, NumTemplateArgs); } } -void CXXNameMangler::mangleUnscopedName(GlobalDecl GD, +void CXXNameMangler::mangleUnscopedName(GlobalDecl GD, const DeclContext *DC, const AbiTagList *AdditionalAbiTags) { - const NamedDecl *ND = cast<NamedDecl>(GD.getDecl()); // <unscoped-name> ::= <unqualified-name> // ::= St <unqualified-name> # ::std:: - if (isStdNamespace(IgnoreLinkageSpecDecls(getEffectiveDeclContext(ND)))) + assert(!isa<LinkageSpecDecl>(DC) && "unskipped LinkageSpecDecl"); + if (isStdNamespace(DC)) Out << "St"; - mangleUnqualifiedName(GD, AdditionalAbiTags); + mangleUnqualifiedName(GD, DC, AdditionalAbiTags); } void CXXNameMangler::mangleUnscopedTemplateName( - GlobalDecl GD, const AbiTagList *AdditionalAbiTags) { + GlobalDecl GD, const DeclContext *DC, const AbiTagList *AdditionalAbiTags) { const TemplateDecl *ND = cast<TemplateDecl>(GD.getDecl()); // <unscoped-template-name> ::= <unscoped-name> // ::= <substitution> @@ -1090,9 +1125,10 @@ void CXXNameMangler::mangleUnscopedTemplateName( "template template param cannot have abi tags"); mangleTemplateParameter(TTP->getDepth(), TTP->getIndex()); } else if (isa<BuiltinTemplateDecl>(ND) || isa<ConceptDecl>(ND)) { - mangleUnscopedName(GD, AdditionalAbiTags); + mangleUnscopedName(GD, DC, AdditionalAbiTags); } else { - mangleUnscopedName(GD.getWithDecl(ND->getTemplatedDecl()), AdditionalAbiTags); + mangleUnscopedName(GD.getWithDecl(ND->getTemplatedDecl()), DC, + AdditionalAbiTags); } addSubstitution(ND); @@ -1368,15 +1404,19 @@ void CXXNameMangler::mangleUnresolvedName( mangleTemplateArgs(TemplateName(), TemplateArgs, NumTemplateArgs); } -void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD, - DeclarationName Name, - unsigned KnownArity, - const AbiTagList *AdditionalAbiTags) { +void CXXNameMangler::mangleUnqualifiedName( + GlobalDecl GD, DeclarationName Name, const DeclContext *DC, + unsigned KnownArity, const AbiTagList *AdditionalAbiTags) { const NamedDecl *ND = cast_or_null<NamedDecl>(GD.getDecl()); - unsigned Arity = KnownArity; - // <unqualified-name> ::= <operator-name> + // <unqualified-name> ::= [<module-name>] <operator-name> // ::= <ctor-dtor-name> - // ::= <source-name> + // ::= [<module-name>] <source-name> + // ::= [<module-name>] DC <source-name>* E + + if (ND && DC && DC->isFileContext()) + mangleModuleName(ND); + + unsigned Arity = KnownArity; switch (Name.getNameKind()) { case DeclarationName::Identifier: { const IdentifierInfo *II = Name.getAsIdentifierInfo(); @@ -1387,8 +1427,6 @@ void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD, // // <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()) @@ -1430,7 +1468,7 @@ void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD, // 12_GLOBAL__N_1 mangling is quite sufficient there, and this better // matches GCC anyway, because GCC does not treat anonymous namespaces as // implying internal linkage. - if (isInternalLinkageDecl(ND)) + if (Context.isInternalLinkageDecl(ND)) Out << 'L'; auto *FD = dyn_cast<FunctionDecl>(ND); @@ -1538,7 +1576,8 @@ void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD, } if (TD->isExternallyVisible()) { - unsigned UnnamedMangle = getASTContext().getManglingNumber(TD); + unsigned UnnamedMangle = + getASTContext().getManglingNumber(TD, Context.isAux()); Out << "Ut"; if (UnnamedMangle > 1) Out << UnnamedMangle - 2; @@ -1685,7 +1724,7 @@ void CXXNameMangler::mangleNestedName(GlobalDecl GD, mangleTemplateArgs(asTemplateName(TD), *TemplateArgs); } else { manglePrefix(DC, NoFunction); - mangleUnqualifiedName(GD, AdditionalAbiTags); + mangleUnqualifiedName(GD, DC, AdditionalAbiTags); } Out << 'E'; @@ -1715,7 +1754,7 @@ void CXXNameMangler::mangleNestedNameWithClosurePrefix( Out << 'N'; mangleClosurePrefix(PrefixND); - mangleUnqualifiedName(GD, AdditionalAbiTags); + mangleUnqualifiedName(GD, nullptr, AdditionalAbiTags); Out << 'E'; } @@ -1745,7 +1784,7 @@ void CXXNameMangler::mangleLocalName(GlobalDecl GD, // <discriminator> := _ <non-negative number> assert(isa<NamedDecl>(D) || isa<BlockDecl>(D)); const RecordDecl *RD = GetLocalClassDecl(D); - const DeclContext *DC = getEffectiveDeclContext(RD ? RD : D); + const DeclContext *DC = Context.getEffectiveDeclContext(RD ? RD : D); Out << 'Z'; @@ -1793,18 +1832,18 @@ void CXXNameMangler::mangleLocalName(GlobalDecl GD, // Mangle the name relative to the closest enclosing function. // equality ok because RD derived from ND above if (D == RD) { - mangleUnqualifiedName(RD, AdditionalAbiTags); + mangleUnqualifiedName(RD, DC, AdditionalAbiTags); } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { if (const NamedDecl *PrefixND = getClosurePrefix(BD)) mangleClosurePrefix(PrefixND, true /*NoFunction*/); else - manglePrefix(getEffectiveDeclContext(BD), true /*NoFunction*/); + manglePrefix(Context.getEffectiveDeclContext(BD), true /*NoFunction*/); assert(!AdditionalAbiTags && "Block cannot have additional abi tags"); mangleUnqualifiedBlock(BD); } else { const NamedDecl *ND = cast<NamedDecl>(D); - mangleNestedName(GD, getEffectiveDeclContext(ND), AdditionalAbiTags, - true /*NoFunction*/); + mangleNestedName(GD, Context.getEffectiveDeclContext(ND), + AdditionalAbiTags, true /*NoFunction*/); } } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { // Mangle a block in a default parameter; see above explanation for @@ -1824,7 +1863,7 @@ void CXXNameMangler::mangleLocalName(GlobalDecl GD, assert(!AdditionalAbiTags && "Block cannot have additional abi tags"); mangleUnqualifiedBlock(BD); } else { - mangleUnqualifiedName(GD, AdditionalAbiTags); + mangleUnqualifiedName(GD, DC, AdditionalAbiTags); } if (const NamedDecl *ND = dyn_cast<NamedDecl>(RD ? RD : D)) { @@ -1843,7 +1882,7 @@ void CXXNameMangler::mangleBlockForPrefix(const BlockDecl *Block) { mangleLocalName(Block, /* AdditionalAbiTags */ nullptr); return; } - const DeclContext *DC = getEffectiveDeclContext(Block); + const DeclContext *DC = Context.getEffectiveDeclContext(Block); if (isLocalContainerContext(DC)) { mangleLocalName(Block, /* AdditionalAbiTags */ nullptr); return; @@ -2010,12 +2049,21 @@ void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) { return; case NestedNameSpecifier::Identifier: + // Clang 14 and before did not consider this substitutable. + bool Clang14Compat = getASTContext().getLangOpts().getClangABICompat() <= + LangOptions::ClangABI::Ver14; + if (!Clang14Compat && mangleSubstitution(qualifier)) + return; + // Member expressions can have these without prefixes, but that // should end up in mangleUnresolvedPrefix instead. assert(qualifier->getPrefix()); manglePrefix(qualifier->getPrefix()); mangleSourceName(qualifier->getAsIdentifier()); + + if (!Clang14Compat) + addSubstitution(qualifier); return; } @@ -2030,7 +2078,7 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { // ::= # empty // ::= <substitution> - DC = IgnoreLinkageSpecDecls(DC); + assert(!isa<LinkageSpecDecl>(DC) && "prefix cannot be LinkageSpecDecl"); if (DC->isTranslationUnit()) return; @@ -2051,10 +2099,11 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { mangleTemplateArgs(asTemplateName(TD), *TemplateArgs); } else if (const NamedDecl *PrefixND = getClosurePrefix(ND)) { mangleClosurePrefix(PrefixND, NoFunction); - mangleUnqualifiedName(ND, nullptr); + mangleUnqualifiedName(ND, nullptr, nullptr); } else { - manglePrefix(getEffectiveDeclContext(ND), NoFunction); - mangleUnqualifiedName(ND, nullptr); + const DeclContext *DC = Context.getEffectiveDeclContext(ND); + manglePrefix(DC, NoFunction); + mangleUnqualifiedName(ND, DC, nullptr); } addSubstitution(ND); @@ -2107,11 +2156,13 @@ void CXXNameMangler::mangleTemplatePrefix(GlobalDecl GD, if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND)) { mangleTemplateParameter(TTP->getDepth(), TTP->getIndex()); } else { - manglePrefix(getEffectiveDeclContext(ND), NoFunction); + const DeclContext *DC = Context.getEffectiveDeclContext(ND); + manglePrefix(DC, NoFunction); if (isa<BuiltinTemplateDecl>(ND) || isa<ConceptDecl>(ND)) - mangleUnqualifiedName(GD, nullptr); + mangleUnqualifiedName(GD, DC, nullptr); else - mangleUnqualifiedName(GD.getWithDecl(ND->getTemplatedDecl()), nullptr); + mangleUnqualifiedName(GD.getWithDecl(ND->getTemplatedDecl()), DC, + nullptr); } addSubstitution(ND); @@ -2152,8 +2203,9 @@ void CXXNameMangler::mangleClosurePrefix(const NamedDecl *ND, bool NoFunction) { mangleTemplatePrefix(TD, NoFunction); mangleTemplateArgs(asTemplateName(TD), *TemplateArgs); } else { - manglePrefix(getEffectiveDeclContext(ND), NoFunction); - mangleUnqualifiedName(ND, nullptr); + const auto *DC = Context.getEffectiveDeclContext(ND); + manglePrefix(DC, NoFunction); + mangleUnqualifiedName(ND, DC, nullptr); } Out << 'M'; @@ -2174,9 +2226,7 @@ void CXXNameMangler::mangleType(TemplateName TN) { switch (TN.getKind()) { case TemplateName::QualifiedTemplate: - TD = TN.getAsQualifiedTemplateName()->getTemplateDecl(); - goto HaveDecl; - + case TemplateName::UsingTemplate: case TemplateName::Template: TD = TN.getAsTemplateDecl(); goto HaveDecl; @@ -2255,6 +2305,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, case Type::FunctionNoProto: case Type::Paren: case Type::Attributed: + case Type::BTFTagAttributed: case Type::Auto: case Type::DeducedTemplateSpecialization: case Type::PackExpansion: @@ -2352,6 +2403,12 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, Out << "_SUBSTPACK_"; break; } + case TemplateName::UsingTemplate: { + TemplateDecl *TD = TN.getAsTemplateDecl(); + assert(TD && !isa<TemplateTemplateParmDecl>(TD)); + mangleSourceNameWithAbiTags(TD); + break; + } } // Note: we don't pass in the template name here. We are mangling the @@ -3098,6 +3155,8 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) { case CC_AAPCS: case CC_AAPCS_VFP: case CC_AArch64VectorCall: + case CC_AArch64SVEPCS: + case CC_AMDGPUKernelCall: case CC_IntelOclBicc: case CC_SpirFunction: case CC_OpenCLKernel: @@ -5514,6 +5573,47 @@ static QualType getLValueType(ASTContext &Ctx, const APValue &LV) { return T; } +static IdentifierInfo *getUnionInitName(SourceLocation UnionLoc, + DiagnosticsEngine &Diags, + const FieldDecl *FD) { + // According to: + // http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling.anonymous + // For the purposes of mangling, the name of an anonymous union is considered + // to be the name of the first named data member found by a pre-order, + // depth-first, declaration-order walk of the data members of the anonymous + // union. + + if (FD->getIdentifier()) + return FD->getIdentifier(); + + // The only cases where the identifer of a FieldDecl would be blank is if the + // field represents an anonymous record type or if it is an unnamed bitfield. + // There is no type to descend into in the case of a bitfield, so we can just + // return nullptr in that case. + if (FD->isBitField()) + return nullptr; + const CXXRecordDecl *RD = FD->getType()->getAsCXXRecordDecl(); + + // Consider only the fields in declaration order, searched depth-first. We + // don't care about the active member of the union, as all we are doing is + // looking for a valid name. We also don't check bases, due to guidance from + // the Itanium ABI folks. + for (const FieldDecl *RDField : RD->fields()) { + if (IdentifierInfo *II = getUnionInitName(UnionLoc, Diags, RDField)) + return II; + } + + // According to the Itanium ABI: If there is no such data member (i.e., if all + // of the data members in the union are unnamed), then there is no way for a + // program to refer to the anonymous union, and there is therefore no need to + // mangle its name. However, we should diagnose this anyway. + unsigned DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Error, "cannot mangle this unnamed union NTTP yet"); + Diags.Report(UnionLoc, DiagID); + + return nullptr; +} + void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V, bool TopLevel, bool NeedExactType) { @@ -5546,8 +5646,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V, assert(RD && "unexpected type for record value"); // Drop trailing zero-initialized elements. - llvm::SmallVector<const FieldDecl *, 16> Fields(RD->field_begin(), - RD->field_end()); + llvm::SmallVector<const FieldDecl *, 16> Fields(RD->fields()); while ( !Fields.empty() && (Fields.back()->isUnnamedBitfield() || @@ -5597,7 +5696,10 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V, mangleType(T); if (!isZeroInitialized(T, V)) { Out << "di"; - mangleSourceName(FD->getIdentifier()); + IdentifierInfo *II = (getUnionInitName( + T->getAsCXXRecordDecl()->getLocation(), Context.getDiags(), FD)); + if (II) + mangleSourceName(II); mangleValueInTemplateArg(FD->getType(), V.getUnionValue(), false); } Out << 'E'; @@ -5930,6 +6032,14 @@ bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) { return mangleSubstitution(reinterpret_cast<uintptr_t>(ND)); } +bool CXXNameMangler::mangleSubstitution(NestedNameSpecifier *NNS) { + assert(NNS->getKind() == NestedNameSpecifier::Identifier && + "mangleSubstitution(NestedNameSpecifier *) is only used for " + "identifier nested name specifiers."); + NNS = Context.getASTContext().getCanonicalNestedNameSpecifier(NNS); + return mangleSubstitution(reinterpret_cast<uintptr_t>(NNS)); +} + /// Determine whether the given type has any qualifiers that are relevant for /// substitutions. static bool hasMangledSubstitutionQualifiers(QualType T) { @@ -5969,56 +6079,67 @@ bool CXXNameMangler::mangleSubstitution(uintptr_t Ptr) { return true; } -static bool isCharType(QualType T) { - if (T.isNull()) +/// Returns whether S is a template specialization of std::Name with a single +/// argument of type A. +bool CXXNameMangler::isSpecializedAs(QualType S, llvm::StringRef Name, + QualType A) { + if (S.isNull()) return false; - return T->isSpecificBuiltinType(BuiltinType::Char_S) || - T->isSpecificBuiltinType(BuiltinType::Char_U); -} - -/// Returns whether a given type is a template specialization of a given name -/// with a single argument of type char. -static bool isCharSpecialization(QualType T, const char *Name) { - if (T.isNull()) - return false; - - const RecordType *RT = T->getAs<RecordType>(); + const RecordType *RT = S->getAs<RecordType>(); if (!RT) return false; const ClassTemplateSpecializationDecl *SD = dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl()); - if (!SD) + if (!SD || !SD->getIdentifier()->isStr(Name)) return false; - if (!isStdNamespace(getEffectiveDeclContext(SD))) + if (!isStdNamespace(Context.getEffectiveDeclContext(SD))) return false; const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs(); if (TemplateArgs.size() != 1) return false; - if (!isCharType(TemplateArgs[0].getAsType())) + if (TemplateArgs[0].getAsType() != A) + return false; + + if (SD->getSpecializedTemplate()->getOwningModuleForLinkage()) return false; - return SD->getIdentifier()->getName() == Name; + return true; } -template <std::size_t StrLen> -static bool isStreamCharSpecialization(const ClassTemplateSpecializationDecl*SD, - const char (&Str)[StrLen]) { - if (!SD->getIdentifier()->isStr(Str)) +/// Returns whether SD is a template specialization std::Name<char, +/// std::char_traits<char> [, std::allocator<char>]> +/// HasAllocator controls whether the 3rd template argument is needed. +bool CXXNameMangler::isStdCharSpecialization( + const ClassTemplateSpecializationDecl *SD, llvm::StringRef Name, + bool HasAllocator) { + if (!SD->getIdentifier()->isStr(Name)) return false; const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs(); - if (TemplateArgs.size() != 2) + if (TemplateArgs.size() != (HasAllocator ? 3 : 2)) return false; - if (!isCharType(TemplateArgs[0].getAsType())) + QualType A = TemplateArgs[0].getAsType(); + if (A.isNull()) + return false; + // Plain 'char' is named Char_S or Char_U depending on the target ABI. + if (!A->isSpecificBuiltinType(BuiltinType::Char_S) && + !A->isSpecificBuiltinType(BuiltinType::Char_U)) return false; - if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits")) + if (!isSpecializedAs(TemplateArgs[1].getAsType(), "char_traits", A)) + return false; + + if (HasAllocator && + !isSpecializedAs(TemplateArgs[2].getAsType(), "allocator", A)) + return false; + + if (SD->getSpecializedTemplate()->getOwningModuleForLinkage()) return false; return true; @@ -6031,10 +6152,14 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) { Out << "St"; return true; } + return false; } if (const ClassTemplateDecl *TD = dyn_cast<ClassTemplateDecl>(ND)) { - if (!isStdNamespace(getEffectiveDeclContext(TD))) + if (!isStdNamespace(Context.getEffectiveDeclContext(TD))) + return false; + + if (TD->getOwningModuleForLinkage()) return false; // <substitution> ::= Sa # ::std::allocator @@ -6048,56 +6173,48 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) { Out << "Sb"; return true; } + return false; } if (const ClassTemplateSpecializationDecl *SD = dyn_cast<ClassTemplateSpecializationDecl>(ND)) { - if (!isStdNamespace(getEffectiveDeclContext(SD))) + if (!isStdNamespace(Context.getEffectiveDeclContext(SD))) + return false; + + if (SD->getSpecializedTemplate()->getOwningModuleForLinkage()) return false; // <substitution> ::= Ss # ::std::basic_string<char, // ::std::char_traits<char>, // ::std::allocator<char> > - if (SD->getIdentifier()->isStr("basic_string")) { - const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs(); - - if (TemplateArgs.size() != 3) - return false; - - if (!isCharType(TemplateArgs[0].getAsType())) - return false; - - if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits")) - return false; - - if (!isCharSpecialization(TemplateArgs[2].getAsType(), "allocator")) - return false; - + if (isStdCharSpecialization(SD, "basic_string", /*HasAllocator=*/true)) { Out << "Ss"; return true; } // <substitution> ::= Si # ::std::basic_istream<char, // ::std::char_traits<char> > - if (isStreamCharSpecialization(SD, "basic_istream")) { + if (isStdCharSpecialization(SD, "basic_istream", /*HasAllocator=*/false)) { Out << "Si"; return true; } // <substitution> ::= So # ::std::basic_ostream<char, // ::std::char_traits<char> > - if (isStreamCharSpecialization(SD, "basic_ostream")) { + if (isStdCharSpecialization(SD, "basic_ostream", /*HasAllocator=*/false)) { Out << "So"; return true; } // <substitution> ::= Sd # ::std::basic_iostream<char, // ::std::char_traits<char> > - if (isStreamCharSpecialization(SD, "basic_iostream")) { + if (isStdCharSpecialization(SD, "basic_iostream", /*HasAllocator=*/false)) { Out << "Sd"; return true; } + return false; } + return false; } @@ -6421,17 +6538,36 @@ void ItaniumMangleContextImpl::mangleLambdaSig(const CXXRecordDecl *Lambda, Mangler.mangleLambdaSig(Lambda); } +void ItaniumMangleContextImpl::mangleModuleInitializer(const Module *M, + raw_ostream &Out) { + // <special-name> ::= GI <module-name> # module initializer function + CXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "_ZGI"; + Mangler.mangleModuleNamePrefix(M->getPrimaryModuleInterfaceName()); + if (M->isModulePartition()) { + // The partition needs including, as partitions can have them too. + auto Partition = M->Name.find(':'); + Mangler.mangleModuleNamePrefix( + StringRef(&M->Name[Partition + 1], M->Name.size() - Partition - 1), + /*IsPartition*/ true); + } +} + ItaniumMangleContext *ItaniumMangleContext::create(ASTContext &Context, - DiagnosticsEngine &Diags) { + DiagnosticsEngine &Diags, + bool IsAux) { return new ItaniumMangleContextImpl( Context, Diags, [](ASTContext &, const NamedDecl *) -> llvm::Optional<unsigned> { return llvm::None; - }); + }, + IsAux); } ItaniumMangleContext * ItaniumMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags, - DiscriminatorOverrideTy DiscriminatorOverride) { - return new ItaniumMangleContextImpl(Context, Diags, DiscriminatorOverride); + DiscriminatorOverrideTy DiscriminatorOverride, + bool IsAux) { + return new ItaniumMangleContextImpl(Context, Diags, DiscriminatorOverride, + IsAux); } diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp index ae585def4d07..87e4255c2b93 100644 --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -1692,3 +1692,18 @@ void JSONNodeDumper::visitVerbatimLineComment( const comments::VerbatimLineComment *C, const comments::FullComment *) { JOS.attribute("text", C->getText()); } + +llvm::json::Object JSONNodeDumper::createFPOptions(FPOptionsOverride FPO) { + llvm::json::Object Ret; +#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ + if (FPO.has##NAME##Override()) \ + Ret.try_emplace(#NAME, static_cast<unsigned>(FPO.get##NAME##Override())); +#include "clang/Basic/FPOptions.def" + return Ret; +} + +void JSONNodeDumper::VisitCompoundStmt(const CompoundStmt *S) { + VisitStmt(S); + if (S->hasStoredFPFeatures()) + JOS.attribute("fpoptions", createFPOptions(S->getStoredFPFeatures())); +} diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp index 984da9909ce2..7ea569c63d9e 100644 --- a/clang/lib/AST/Mangle.cpp +++ b/clang/lib/AST/Mangle.cpp @@ -70,11 +70,9 @@ static CCMangling getCallingConvMangling(const ASTContext &Context, // On wasm, the argc/argv form of "main" is renamed so that the startup code // can call it with the correct function signature. - // On Emscripten, users may be exporting "main" and expecting to call it - // themselves, so we can't mangle it. - if (Triple.isWasm() && !Triple.isOSEmscripten()) + if (Triple.isWasm()) if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) - if (FD->isMain() && FD->hasPrototype() && FD->param_size() == 2) + if (FD->isMain() && FD->getNumParams() == 2) return CCM_WasmMainArgcArgv; if (!Triple.isOSWindows() || !Triple.isX86()) diff --git a/clang/lib/AST/MicrosoftCXXABI.cpp b/clang/lib/AST/MicrosoftCXXABI.cpp index b7dc0e62e66a..7f4a7b2b9381 100644 --- a/clang/lib/AST/MicrosoftCXXABI.cpp +++ b/clang/lib/AST/MicrosoftCXXABI.cpp @@ -69,6 +69,7 @@ class MSHIPNumberingContext : public MicrosoftNumberingContext { std::unique_ptr<MangleNumberingContext> DeviceCtx; public: + using MicrosoftNumberingContext::getManglingNumber; MSHIPNumberingContext(MangleContext *DeviceMangler) { DeviceCtx = createItaniumNumberingContext(DeviceMangler); } @@ -76,6 +77,20 @@ public: unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override { return DeviceCtx->getManglingNumber(CallOperator); } + + unsigned getManglingNumber(const TagDecl *TD, + unsigned MSLocalManglingNumber) override { + unsigned DeviceN = DeviceCtx->getManglingNumber(TD, MSLocalManglingNumber); + unsigned HostN = + MicrosoftNumberingContext::getManglingNumber(TD, MSLocalManglingNumber); + if (DeviceN > 0xFFFF || HostN > 0xFFFF) { + DiagnosticsEngine &Diags = TD->getASTContext().getDiagnostics(); + unsigned DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Error, "Mangling number exceeds limit (65535)"); + Diags.Report(TD->getLocation(), DiagID); + } + return (DeviceN << 16) | HostN; + } }; class MSSYCLNumberingContext : public MicrosoftNumberingContext { diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 8802b6e500a6..09075e60142a 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -147,7 +147,8 @@ class MicrosoftMangleContextImpl : public MicrosoftMangleContext { SmallString<16> AnonymousNamespaceHash; public: - MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags); + MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags, + bool IsAux = false); bool shouldMangleCXXName(const NamedDecl *D) override; bool shouldMangleStringLiteral(const StringLiteral *SL) override; void mangleCXXName(GlobalDecl GD, raw_ostream &Out) override; @@ -221,7 +222,7 @@ public: // Use the canonical number for externally visible decls. if (ND->isExternallyVisible()) { - disc = getASTContext().getManglingNumber(ND); + disc = getASTContext().getManglingNumber(ND, isAux()); return true; } @@ -459,8 +460,9 @@ private: } MicrosoftMangleContextImpl::MicrosoftMangleContextImpl(ASTContext &Context, - DiagnosticsEngine &Diags) - : MicrosoftMangleContext(Context, Diags) { + DiagnosticsEngine &Diags, + bool IsAux) + : MicrosoftMangleContext(Context, Diags, IsAux) { // To mangle anonymous namespaces, hash the path to the main source file. The // path should be whatever (probably relative) path was passed on the command // line. The goal is for the compiler to produce the same output regardless of @@ -806,8 +808,8 @@ void MicrosoftCXXNameMangler::mangleNumber(llvm::APSInt Number) { // to convert every integer to signed 64 bit before mangling (including // unsigned 64 bit values). Do the same, but preserve bits beyond the bottom // 64. - llvm::APInt Value = - Number.isSigned() ? Number.sextOrSelf(64) : Number.zextOrSelf(64); + unsigned Width = std::max(Number.getBitWidth(), 64U); + llvm::APInt Value = Number.extend(Width); // <non-negative integer> ::= A@ # when Number == 0 // ::= <decimal digit> # when 1 <= Number <= 10 @@ -1943,7 +1945,7 @@ void MicrosoftCXXNameMangler::mangleObjCKindOfType(const ObjCObjectType *T, Extra.mangleSourceName("KindOf"); Extra.mangleType(QualType(T, 0) .stripObjCKindOfType(getASTContext()) - ->getAs<ObjCObjectType>(), + ->castAs<ObjCObjectType>(), Quals, Range); mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__ObjC"}); @@ -2459,7 +2461,12 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, break; case BuiltinType::Half: - mangleArtificialTagType(TTK_Struct, "_Half", {"__clang"}); + if (!getASTContext().getLangOpts().HLSL) + mangleArtificialTagType(TTK_Struct, "_Half", {"__clang"}); + else if (getASTContext().getLangOpts().NativeHalfType) + Out << "$f16@"; + else + Out << "$halff@"; break; #define SVE_TYPE(Name, Id, SingletonId) \ @@ -3944,7 +3951,8 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, Mangler.getStream() << '@'; } -MicrosoftMangleContext * -MicrosoftMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) { - return new MicrosoftMangleContextImpl(Context, Diags); +MicrosoftMangleContext *MicrosoftMangleContext::create(ASTContext &Context, + DiagnosticsEngine &Diags, + bool IsAux) { + return new MicrosoftMangleContextImpl(Context, Diags, IsAux); } diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 735bcff8f113..04cbb09356d7 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -150,6 +150,7 @@ void ODRHash::AddTemplateName(TemplateName Name) { case TemplateName::DependentTemplate: case TemplateName::SubstTemplateTemplateParm: case TemplateName::SubstTemplateTemplateParmPack: + case TemplateName::UsingTemplate: break; } } diff --git a/clang/lib/AST/OSLog.cpp b/clang/lib/AST/OSLog.cpp index 4cc5def0651f..40fa8c3802c3 100644 --- a/clang/lib/AST/OSLog.cpp +++ b/clang/lib/AST/OSLog.cpp @@ -201,7 +201,7 @@ bool clang::analyze_os_log::computeOSLogBufferLayout( } const StringLiteral *Lit = cast<StringLiteral>(StringArg->IgnoreParenCasts()); - assert(Lit && (Lit->isAscii() || Lit->isUTF8())); + assert(Lit && (Lit->isOrdinary() || Lit->isUTF8())); StringRef Data = Lit->getString(); OSLogFormatStringHandler H(VarArgs); ParsePrintfString(H, Data.begin(), Data.end(), Ctx.getLangOpts(), diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index 1bd049b88005..dc2d90e366bc 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -146,6 +146,7 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { case OMPC_use_device_ptr: case OMPC_use_device_addr: case OMPC_is_device_ptr: + case OMPC_has_device_addr: case OMPC_unified_address: case OMPC_unified_shared_memory: case OMPC_reverse_offload: @@ -244,6 +245,7 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) case OMPC_use_device_ptr: case OMPC_use_device_addr: case OMPC_is_device_ptr: + case OMPC_has_device_addr: case OMPC_unified_address: case OMPC_unified_shared_memory: case OMPC_reverse_offload: @@ -1038,19 +1040,19 @@ OMPDepobjClause *OMPDepobjClause::CreateEmpty(const ASTContext &C) { OMPDependClause * OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, - Expr *DepModifier, OpenMPDependClauseKind DepKind, - SourceLocation DepLoc, SourceLocation ColonLoc, + DependDataTy Data, Expr *DepModifier, ArrayRef<Expr *> VL, unsigned NumLoops) { void *Mem = C.Allocate( totalSizeToAlloc<Expr *>(VL.size() + /*depend-modifier*/ 1 + NumLoops), alignof(OMPDependClause)); OMPDependClause *Clause = new (Mem) OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size(), NumLoops); - Clause->setVarRefs(VL); - Clause->setDependencyKind(DepKind); - Clause->setDependencyLoc(DepLoc); - Clause->setColonLoc(ColonLoc); + Clause->setDependencyKind(Data.DepKind); + Clause->setDependencyLoc(Data.DepLoc); + Clause->setColonLoc(Data.ColonLoc); + Clause->setOmpAllMemoryLoc(Data.OmpAllMemoryLoc); Clause->setModifier(DepModifier); + Clause->setVarRefs(VL); for (unsigned I = 0 ; I < NumLoops; ++I) Clause->setLoopData(I, nullptr); return Clause; @@ -1432,6 +1434,53 @@ OMPIsDevicePtrClause::CreateEmpty(const ASTContext &C, return new (Mem) OMPIsDevicePtrClause(Sizes); } +OMPHasDeviceAddrClause * +OMPHasDeviceAddrClause::Create(const ASTContext &C, const OMPVarListLocTy &Locs, + ArrayRef<Expr *> Vars, + ArrayRef<ValueDecl *> Declarations, + MappableExprComponentListsRef ComponentLists) { + OMPMappableExprListSizeTy Sizes; + Sizes.NumVars = Vars.size(); + Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations); + Sizes.NumComponentLists = ComponentLists.size(); + Sizes.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>( + Sizes.NumVars, Sizes.NumUniqueDeclarations, + Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, + Sizes.NumComponents)); + + auto *Clause = new (Mem) OMPHasDeviceAddrClause(Locs, Sizes); + + Clause->setVarRefs(Vars); + Clause->setClauseInfo(Declarations, ComponentLists); + return Clause; +} + +OMPHasDeviceAddrClause * +OMPHasDeviceAddrClause::CreateEmpty(const ASTContext &C, + const OMPMappableExprListSizeTy &Sizes) { + void *Mem = C.Allocate( + totalSizeToAlloc<Expr *, ValueDecl *, unsigned, + OMPClauseMappableExprCommon::MappableComponent>( + Sizes.NumVars, Sizes.NumUniqueDeclarations, + Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, + Sizes.NumComponents)); + return new (Mem) OMPHasDeviceAddrClause(Sizes); +} + OMPNontemporalClause *OMPNontemporalClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, @@ -2134,11 +2183,23 @@ void OMPClausePrinter::VisitOMPDependClause(OMPDependClause *Node) { DepModifier->printPretty(OS, nullptr, Policy); OS << ", "; } - OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), - Node->getDependencyKind()); - if (!Node->varlist_empty()) { + OpenMPDependClauseKind DepKind = Node->getDependencyKind(); + OpenMPDependClauseKind PrintKind = DepKind; + bool IsOmpAllMemory = false; + if (PrintKind == OMPC_DEPEND_outallmemory) { + PrintKind = OMPC_DEPEND_out; + IsOmpAllMemory = true; + } else if (PrintKind == OMPC_DEPEND_inoutallmemory) { + PrintKind = OMPC_DEPEND_inout; + IsOmpAllMemory = true; + } + OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), PrintKind); + if (!Node->varlist_empty() || IsOmpAllMemory) OS << " :"; - VisitOMPClauseList(Node, ' '); + VisitOMPClauseList(Node, ' '); + if (IsOmpAllMemory) { + OS << (Node->varlist_empty() ? " " : ","); + OS << "omp_all_memory"; } OS << ")"; } @@ -2259,6 +2320,14 @@ void OMPClausePrinter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *Node) { } } +void OMPClausePrinter::VisitOMPHasDeviceAddrClause(OMPHasDeviceAddrClause *Node) { + if (!Node->varlist_empty()) { + OS << "has_device_addr"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} + void OMPClausePrinter::VisitOMPNontemporalClause(OMPNontemporalClause *Node) { if (!Node->varlist_empty()) { OS << "nontemporal"; diff --git a/clang/lib/AST/ParentMapContext.cpp b/clang/lib/AST/ParentMapContext.cpp index d216be5b59e8..e0d4700e4b10 100644 --- a/clang/lib/AST/ParentMapContext.cpp +++ b/clang/lib/AST/ParentMapContext.cpp @@ -330,6 +330,9 @@ template <> DynTypedNode createDynTypedNode(const NestedNameSpecifierLoc &Node) { return DynTypedNode::create(Node); } +template <> DynTypedNode createDynTypedNode(const ObjCProtocolLoc &Node) { + return DynTypedNode::create(Node); +} /// @} /// A \c RecursiveASTVisitor that builds a map from nodes to their @@ -398,11 +401,14 @@ private: } } + template <typename T> static bool isNull(T Node) { return !Node; } + static bool isNull(ObjCProtocolLoc Node) { return false; } + template <typename T, typename MapNodeTy, typename BaseTraverseFn, typename MapTy> bool TraverseNode(T Node, MapNodeTy MapNode, BaseTraverseFn BaseTraverse, MapTy *Parents) { - if (!Node) + if (isNull(Node)) return true; addParent(MapNode, Parents); ParentStack.push_back(createDynTypedNode(Node)); @@ -433,6 +439,12 @@ private: AttrNode, AttrNode, [&] { return VisitorBase::TraverseAttr(AttrNode); }, &Map.PointerParents); } + bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLocNode) { + return TraverseNode( + ProtocolLocNode, DynTypedNode::create(ProtocolLocNode), + [&] { return VisitorBase::TraverseObjCProtocolLoc(ProtocolLocNode); }, + &Map.OtherParents); + } // Using generic TraverseNode for Stmt would prevent data-recursion. bool dataTraverseStmtPre(Stmt *StmtNode) { diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp index 561757b1ba64..26aaa96a1dc6 100644 --- a/clang/lib/AST/QualTypeNames.cpp +++ b/clang/lib/AST/QualTypeNames.cpp @@ -80,8 +80,12 @@ static bool getFullyQualifiedTemplateName(const ASTContext &Ctx, Ctx, ArgTDecl, true, WithGlobalNsPrefix); } if (NNS) { - TName = Ctx.getQualifiedTemplateName(NNS, - /*TemplateKeyword=*/false, ArgTDecl); + TemplateName UnderlyingTN(ArgTDecl); + if (UsingShadowDecl *USD = TName.getAsUsingShadowDecl()) + UnderlyingTN = TemplateName(USD); + TName = + Ctx.getQualifiedTemplateName(NNS, + /*TemplateKeyword=*/false, UnderlyingTN); Changed = true; } return Changed; diff --git a/clang/lib/AST/Randstruct.cpp b/clang/lib/AST/Randstruct.cpp new file mode 100644 index 000000000000..99c665f420e6 --- /dev/null +++ b/clang/lib/AST/Randstruct.cpp @@ -0,0 +1,231 @@ +//===--- Randstruct.cpp ---------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains the implementation for Clang's structure field layout +// randomization. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/Randstruct.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTDiagnostic.h" +#include "clang/AST/Attr.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" // For StaticAssertDecl +#include "clang/Basic/Diagnostic.h" +#include "llvm/ADT/SmallVector.h" + +#include <algorithm> +#include <random> +#include <set> +#include <sstream> +#include <string> + +using clang::ASTContext; +using clang::FieldDecl; +using llvm::SmallVector; + +namespace { + +// FIXME: Replace this with some discovery once that mechanism exists. +enum { CACHE_LINE = 64 }; + +// The Bucket class holds the struct fields we're trying to fill to a +// cache-line. +class Bucket { + SmallVector<FieldDecl *, 64> Fields; + int Size = 0; + +public: + virtual ~Bucket() = default; + + SmallVector<FieldDecl *, 64> &fields() { return Fields; } + void addField(FieldDecl *Field, int FieldSize); + virtual bool canFit(int FieldSize) const { + return Size + FieldSize <= CACHE_LINE; + } + virtual bool isBitfieldRun() const { return false; } + bool full() const { return Size >= CACHE_LINE; } +}; + +void Bucket::addField(FieldDecl *Field, int FieldSize) { + Size += FieldSize; + Fields.push_back(Field); +} + +struct BitfieldRunBucket : public Bucket { + bool canFit(int FieldSize) const override { return true; } + bool isBitfieldRun() const override { return true; } +}; + +void randomizeStructureLayoutImpl(const ASTContext &Context, + llvm::SmallVectorImpl<FieldDecl *> &FieldsOut, + std::mt19937 &RNG) { + // All of the Buckets produced by best-effort cache-line algorithm. + SmallVector<std::unique_ptr<Bucket>, 16> Buckets; + + // The current bucket of fields that we are trying to fill to a cache-line. + std::unique_ptr<Bucket> CurrentBucket; + + // The current bucket containing the run of adjacent bitfields to ensure they + // remain adjacent. + std::unique_ptr<BitfieldRunBucket> CurrentBitfieldRun; + + // Tracks the number of fields that we failed to fit to the current bucket, + // and thus still need to be added later. + size_t Skipped = 0; + + while (!FieldsOut.empty()) { + // If we've Skipped more fields than we have remaining to place, that means + // that they can't fit in our current bucket, and we need to start a new + // one. + if (Skipped >= FieldsOut.size()) { + Skipped = 0; + Buckets.push_back(std::move(CurrentBucket)); + } + + // Take the first field that needs to be put in a bucket. + auto FieldIter = FieldsOut.begin(); + FieldDecl *FD = *FieldIter; + + if (FD->isBitField() && !FD->isZeroLengthBitField(Context)) { + // Start a bitfield run if this is the first bitfield we have found. + if (!CurrentBitfieldRun) + CurrentBitfieldRun = std::make_unique<BitfieldRunBucket>(); + + // We've placed the field, and can remove it from the "awaiting Buckets" + // vector called "Fields." + CurrentBitfieldRun->addField(FD, /*FieldSize is irrelevant here*/ 1); + FieldsOut.erase(FieldIter); + continue; + } + + // Else, current field is not a bitfield. If we were previously in a + // bitfield run, end it. + if (CurrentBitfieldRun) + Buckets.push_back(std::move(CurrentBitfieldRun)); + + // If we don't have a bucket, make one. + if (!CurrentBucket) + CurrentBucket = std::make_unique<Bucket>(); + + uint64_t Width = Context.getTypeInfo(FD->getType()).Width; + if (Width >= CACHE_LINE) { + std::unique_ptr<Bucket> OverSized = std::make_unique<Bucket>(); + OverSized->addField(FD, Width); + FieldsOut.erase(FieldIter); + Buckets.push_back(std::move(OverSized)); + continue; + } + + // If it fits, add it. + if (CurrentBucket->canFit(Width)) { + CurrentBucket->addField(FD, Width); + FieldsOut.erase(FieldIter); + + // If it's now full, tie off the bucket. + if (CurrentBucket->full()) { + Skipped = 0; + Buckets.push_back(std::move(CurrentBucket)); + } + } else { + // We can't fit it in our current bucket. Move to the end for processing + // later. + ++Skipped; // Mark it skipped. + FieldsOut.push_back(FD); + FieldsOut.erase(FieldIter); + } + } + + // Done processing the fields awaiting a bucket. + + // If we were filling a bucket, tie it off. + if (CurrentBucket) + Buckets.push_back(std::move(CurrentBucket)); + + // If we were processing a bitfield run bucket, tie it off. + if (CurrentBitfieldRun) + Buckets.push_back(std::move(CurrentBitfieldRun)); + + std::shuffle(std::begin(Buckets), std::end(Buckets), RNG); + + // Produce the new ordering of the elements from the Buckets. + SmallVector<FieldDecl *, 16> FinalOrder; + for (const std::unique_ptr<Bucket> &B : Buckets) { + llvm::SmallVectorImpl<FieldDecl *> &RandFields = B->fields(); + if (!B->isBitfieldRun()) + std::shuffle(std::begin(RandFields), std::end(RandFields), RNG); + + FinalOrder.insert(FinalOrder.end(), RandFields.begin(), RandFields.end()); + } + + FieldsOut = FinalOrder; +} + +} // anonymous namespace + +namespace clang { +namespace randstruct { + +bool randomizeStructureLayout(const ASTContext &Context, RecordDecl *RD, + SmallVectorImpl<Decl *> &FinalOrdering) { + SmallVector<FieldDecl *, 64> RandomizedFields; + SmallVector<Decl *, 8> PostRandomizedFields; + + unsigned TotalNumFields = 0; + for (Decl *D : RD->decls()) { + ++TotalNumFields; + if (auto *FD = dyn_cast<FieldDecl>(D)) + RandomizedFields.push_back(FD); + else if (isa<StaticAssertDecl>(D) || isa<IndirectFieldDecl>(D)) + PostRandomizedFields.push_back(D); + else + FinalOrdering.push_back(D); + } + + if (RandomizedFields.empty()) + return false; + + // Struct might end with a flexible array or an array of size 0 or 1, + // in which case we don't want to randomize it. + FieldDecl *FlexibleArray = + RD->hasFlexibleArrayMember() ? RandomizedFields.pop_back_val() : nullptr; + if (!FlexibleArray) { + if (const auto *CA = + dyn_cast<ConstantArrayType>(RandomizedFields.back()->getType())) + if (CA->getSize().sle(2)) + FlexibleArray = RandomizedFields.pop_back_val(); + } + + std::string Seed = + Context.getLangOpts().RandstructSeed + RD->getNameAsString(); + std::seed_seq SeedSeq(Seed.begin(), Seed.end()); + std::mt19937 RNG(SeedSeq); + + randomizeStructureLayoutImpl(Context, RandomizedFields, RNG); + + // Plorp the randomized decls into the final ordering. + FinalOrdering.insert(FinalOrdering.end(), RandomizedFields.begin(), + RandomizedFields.end()); + + // Add fields that belong towards the end of the RecordDecl. + FinalOrdering.insert(FinalOrdering.end(), PostRandomizedFields.begin(), + PostRandomizedFields.end()); + + // Add back the flexible array. + if (FlexibleArray) + FinalOrdering.push_back(FlexibleArray); + + assert(TotalNumFields == FinalOrdering.size() && + "Decl count has been altered after Randstruct randomization!"); + (void)TotalNumFields; + return true; +} + +} // end namespace randstruct +} // end namespace clang diff --git a/clang/lib/AST/RawCommentList.cpp b/clang/lib/AST/RawCommentList.cpp index a8d15036cab9..c3beb2322888 100644 --- a/clang/lib/AST/RawCommentList.cpp +++ b/clang/lib/AST/RawCommentList.cpp @@ -16,6 +16,7 @@ #include "clang/AST/CommentSema.h" #include "clang/Basic/CharInfo.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Support/Allocator.h" using namespace clang; @@ -362,6 +363,24 @@ std::string RawComment::getFormattedText(const SourceManager &SourceMgr, if (CommentText.empty()) return ""; + std::string Result; + for (const RawComment::CommentLine &Line : + getFormattedLines(SourceMgr, Diags)) + Result += Line.Text + "\n"; + + auto LastChar = Result.find_last_not_of('\n'); + Result.erase(LastChar + 1, Result.size()); + + return Result; +} + +std::vector<RawComment::CommentLine> +RawComment::getFormattedLines(const SourceManager &SourceMgr, + DiagnosticsEngine &Diags) const { + llvm::StringRef CommentText = getRawText(SourceMgr); + if (CommentText.empty()) + return {}; + llvm::BumpPtrAllocator Allocator; // We do not parse any commands, so CommentOptions are ignored by // comments::Lexer. Therefore, we just use default-constructed options. @@ -371,13 +390,23 @@ std::string RawComment::getFormattedText(const SourceManager &SourceMgr, CommentText.begin(), CommentText.end(), /*ParseCommands=*/false); - std::string Result; + std::vector<RawComment::CommentLine> Result; // A column number of the first non-whitespace token in the comment text. // We skip whitespace up to this column, but keep the whitespace after this // column. IndentColumn is calculated when lexing the first line and reused // for the rest of lines. unsigned IndentColumn = 0; + // Record the line number of the last processed comment line. + // For block-style comments, an extra newline token will be produced after + // the end-comment marker, e.g.: + // /** This is a multi-line comment block. + // The lexer will produce two newline tokens here > */ + // previousLine will record the line number when we previously saw a newline + // token and recorded a comment line. If we see another newline token on the + // same line, don't record anything in between. + unsigned PreviousLine = 0; + // Processes one line of the comment and adds it to the result. // Handles skipping the indent at the start of the line. // Returns false when eof is reached and true otherwise. @@ -389,9 +418,14 @@ std::string RawComment::getFormattedText(const SourceManager &SourceMgr, if (Tok.is(comments::tok::eof)) return false; if (Tok.is(comments::tok::newline)) { - Result += "\n"; + PresumedLoc Loc = SourceMgr.getPresumedLoc(Tok.getLocation()); + if (Loc.getLine() != PreviousLine) { + Result.emplace_back("", Loc, Loc); + PreviousLine = Loc.getLine(); + } return true; } + SmallString<124> Line; llvm::StringRef TokText = L.getSpelling(Tok, SourceMgr); bool LocInvalid = false; unsigned TokColumn = @@ -417,32 +451,35 @@ std::string RawComment::getFormattedText(const SourceManager &SourceMgr, WhitespaceLen, std::max<int>(static_cast<int>(IndentColumn) - TokColumn, 0)); llvm::StringRef Trimmed = TokText.drop_front(SkipLen); - Result += Trimmed; + Line += Trimmed; + // Get the beginning location of the adjusted comment line. + PresumedLoc Begin = + SourceMgr.getPresumedLoc(Tok.getLocation().getLocWithOffset(SkipLen)); + // Lex all tokens in the rest of the line. for (L.lex(Tok); Tok.isNot(comments::tok::eof); L.lex(Tok)) { if (Tok.is(comments::tok::newline)) { - Result += "\n"; + // Get the ending location of the comment line. + PresumedLoc End = SourceMgr.getPresumedLoc(Tok.getLocation()); + if (End.getLine() != PreviousLine) { + Result.emplace_back(Line, Begin, End); + PreviousLine = End.getLine(); + } return true; } - Result += L.getSpelling(Tok, SourceMgr); + Line += L.getSpelling(Tok, SourceMgr); } + PresumedLoc End = SourceMgr.getPresumedLoc(Tok.getLocation()); + Result.emplace_back(Line, Begin, End); // We've reached the end of file token. return false; }; - auto DropTrailingNewLines = [](std::string &Str) { - while (!Str.empty() && Str.back() == '\n') - Str.pop_back(); - }; - // Process first line separately to remember indent for the following lines. - if (!LexLine(/*IsFirstLine=*/true)) { - DropTrailingNewLines(Result); + if (!LexLine(/*IsFirstLine=*/true)) return Result; - } // Process the rest of the lines. while (LexLine(/*IsFirstLine=*/false)) ; - DropTrailingNewLines(Result); return Result; } diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 709e05716a56..6f3ede2ce42a 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -1223,7 +1223,7 @@ ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { // Per GCC's documentation, it only applies to non-static data members. return (Packed && ((Context.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver6) || - Context.getTargetInfo().getTriple().isPS4() || + Context.getTargetInfo().getTriple().isPS() || Context.getTargetInfo().getTriple().isOSAIX())) ? CharUnits::One() : UnpackedAlign; @@ -1261,7 +1261,9 @@ ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { (!HasExternalLayout || Offset == CharUnits::Zero()) && EmptySubobjects->CanPlaceBaseAtOffset(Base, CharUnits::Zero())) { setSize(std::max(getSize(), Layout.getSize())); - UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign); + // On PS4/PS5, don't update the alignment, to preserve compatibility. + if (!Context.getTargetInfo().getTriple().isPS()) + UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign); return CharUnits::Zero(); } @@ -1890,8 +1892,8 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D, llvm::Triple Target = Context.getTargetInfo().getTriple(); bool FieldPacked = (Packed && (!FieldClass || FieldClass->isPOD() || Context.getLangOpts().getClangABICompat() <= - LangOptions::ClangABI::Ver13 || - Target.isPS4() || Target.isOSDarwin())) || + LangOptions::ClangABI::Ver14 || + Target.isPS() || Target.isOSDarwin())) || D->hasAttr<PackedAttr>(); AlignRequirementKind AlignRequirement = AlignRequirementKind::None; @@ -3545,7 +3547,7 @@ static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, auto CXXRD = dyn_cast<CXXRecordDecl>(RD); PrintOffset(OS, Offset, IndentLevel); - OS << C.getTypeDeclType(const_cast<RecordDecl*>(RD)).getAsString(); + OS << C.getTypeDeclType(const_cast<RecordDecl *>(RD)); if (Description) OS << ' ' << Description; if (CXXRD && CXXRD->isEmpty()) @@ -3630,7 +3632,7 @@ static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, const QualType &FieldType = C.getLangOpts().DumpRecordLayoutsCanonical ? Field.getType().getCanonicalType() : Field.getType(); - OS << FieldType.getAsString() << ' ' << Field << '\n'; + OS << FieldType << ' ' << Field << '\n'; } // Dump virtual bases. @@ -3696,7 +3698,7 @@ void ASTContext::DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS, // in libFrontend. const ASTRecordLayout &Info = getASTRecordLayout(RD); - OS << "Type: " << getTypeDeclType(RD).getAsString() << "\n"; + OS << "Type: " << getTypeDeclType(RD) << "\n"; OS << "\nLayout: "; OS << "<ASTRecordLayout\n"; OS << " Size:" << toBits(Info.getSize()) << "\n"; diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index be19d3b2cce2..8eae04d0d9fd 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -361,12 +361,14 @@ int64_t Stmt::getID(const ASTContext &Context) const { return Context.getAllocator().identifyKnownAlignedObject<Stmt>(this); } -CompoundStmt::CompoundStmt(ArrayRef<Stmt *> Stmts, SourceLocation LB, - SourceLocation RB) - : Stmt(CompoundStmtClass), RBraceLoc(RB) { +CompoundStmt::CompoundStmt(ArrayRef<Stmt *> Stmts, FPOptionsOverride FPFeatures, + SourceLocation LB, SourceLocation RB) + : Stmt(CompoundStmtClass), LBraceLoc(LB), RBraceLoc(RB) { CompoundStmtBits.NumStmts = Stmts.size(); + CompoundStmtBits.HasFPFeatures = FPFeatures.requiresTrailingStorage(); setStmts(Stmts); - CompoundStmtBits.LBraceLoc = LB; + if (hasStoredFPFeatures()) + setStoredFPFeatures(FPFeatures); } void CompoundStmt::setStmts(ArrayRef<Stmt *> Stmts) { @@ -377,18 +379,23 @@ void CompoundStmt::setStmts(ArrayRef<Stmt *> Stmts) { } CompoundStmt *CompoundStmt::Create(const ASTContext &C, ArrayRef<Stmt *> Stmts, + FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB) { void *Mem = - C.Allocate(totalSizeToAlloc<Stmt *>(Stmts.size()), alignof(CompoundStmt)); - return new (Mem) CompoundStmt(Stmts, LB, RB); + C.Allocate(totalSizeToAlloc<Stmt *, FPOptionsOverride>( + Stmts.size(), FPFeatures.requiresTrailingStorage()), + alignof(CompoundStmt)); + return new (Mem) CompoundStmt(Stmts, FPFeatures, LB, RB); } -CompoundStmt *CompoundStmt::CreateEmpty(const ASTContext &C, - unsigned NumStmts) { - void *Mem = - C.Allocate(totalSizeToAlloc<Stmt *>(NumStmts), alignof(CompoundStmt)); +CompoundStmt *CompoundStmt::CreateEmpty(const ASTContext &C, unsigned NumStmts, + bool HasFPFeatures) { + void *Mem = C.Allocate( + totalSizeToAlloc<Stmt *, FPOptionsOverride>(NumStmts, HasFPFeatures), + alignof(CompoundStmt)); CompoundStmt *New = new (Mem) CompoundStmt(EmptyShell()); New->CompoundStmtBits.NumStmts = NumStmts; + New->CompoundStmtBits.HasFPFeatures = HasFPFeatures; return New; } diff --git a/clang/lib/AST/StmtCXX.cpp b/clang/lib/AST/StmtCXX.cpp index 060d090fc06a..33b0421ad101 100644 --- a/clang/lib/AST/StmtCXX.cpp +++ b/clang/lib/AST/StmtCXX.cpp @@ -118,7 +118,6 @@ CoroutineBodyStmt::CoroutineBodyStmt(CoroutineBodyStmt::CtorArgs const &Args) SubStmts[CoroutineBodyStmt::Allocate] = Args.Allocate; SubStmts[CoroutineBodyStmt::Deallocate] = Args.Deallocate; SubStmts[CoroutineBodyStmt::ReturnValue] = Args.ReturnValue; - SubStmts[CoroutineBodyStmt::ResultDecl] = Args.ResultDecl; SubStmts[CoroutineBodyStmt::ReturnStmt] = Args.ReturnStmt; SubStmts[CoroutineBodyStmt::ReturnStmtOnAllocFailure] = Args.ReturnStmtOnAllocFailure; diff --git a/clang/lib/AST/StmtOpenMP.cpp b/clang/lib/AST/StmtOpenMP.cpp index 8a9f73d3dbf0..e0a4221db7ec 100644 --- a/clang/lib/AST/StmtOpenMP.cpp +++ b/clang/lib/AST/StmtOpenMP.cpp @@ -682,6 +682,22 @@ OMPParallelMasterDirective::CreateEmpty(const ASTContext &C, C, NumClauses, /*HasAssociatedStmt=*/true, /*NumChildren=*/1); } +OMPParallelMaskedDirective *OMPParallelMaskedDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef) { + auto *Dir = createDirective<OMPParallelMaskedDirective>( + C, Clauses, AssociatedStmt, /*NumChildren=*/1, StartLoc, EndLoc); + Dir->setTaskReductionRefExpr(TaskRedRef); + return Dir; +} + +OMPParallelMaskedDirective * +OMPParallelMaskedDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell) { + return createEmptyDirective<OMPParallelMaskedDirective>( + C, NumClauses, /*HasAssociatedStmt=*/true, /*NumChildren=*/1); +} + OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, @@ -863,18 +879,22 @@ OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C, !IsStandalone); } -OMPAtomicDirective *OMPAtomicDirective::Create( - const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V, - Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate) { +OMPAtomicDirective * +OMPAtomicDirective::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, Expressions Exprs) { auto *Dir = createDirective<OMPAtomicDirective>( - C, Clauses, AssociatedStmt, /*NumChildren=*/4, StartLoc, EndLoc); - Dir->setX(X); - Dir->setV(V); - Dir->setExpr(E); - Dir->setUpdateExpr(UE); - Dir->IsXLHSInRHSPart = IsXLHSInRHSPart; - Dir->IsPostfixUpdate = IsPostfixUpdate; + C, Clauses, AssociatedStmt, /*NumChildren=*/7, StartLoc, EndLoc); + Dir->setX(Exprs.X); + Dir->setV(Exprs.V); + Dir->setR(Exprs.R); + Dir->setExpr(Exprs.E); + Dir->setUpdateExpr(Exprs.UE); + Dir->setD(Exprs.D); + Dir->setCond(Exprs.Cond); + Dir->Flags.IsXLHSInRHSPart = Exprs.IsXLHSInRHSPart ? 1 : 0; + Dir->Flags.IsPostfixUpdate = Exprs.IsPostfixUpdate ? 1 : 0; + Dir->Flags.IsFailOnly = Exprs.IsFailOnly ? 1 : 0; return Dir; } @@ -882,7 +902,7 @@ OMPAtomicDirective *OMPAtomicDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { return createEmptyDirective<OMPAtomicDirective>( - C, NumClauses, /*HasAssociatedStmt=*/true, /*NumChildren=*/4); + C, NumClauses, /*HasAssociatedStmt=*/true, /*NumChildren=*/7); } OMPTargetDirective *OMPTargetDirective::Create(const ASTContext &C, @@ -1156,6 +1176,51 @@ OMPMasterTaskLoopDirective::CreateEmpty(const ASTContext &C, numLoopChildren(CollapsedNum, OMPD_master_taskloop), CollapsedNum); } +OMPMaskedTaskLoopDirective *OMPMaskedTaskLoopDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs, bool HasCancel) { + auto *Dir = createDirective<OMPMaskedTaskLoopDirective>( + C, Clauses, AssociatedStmt, + numLoopChildren(CollapsedNum, OMPD_masked_taskloop), StartLoc, EndLoc, + CollapsedNum); + 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->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setDependentCounters(Exprs.DependentCounters); + Dir->setDependentInits(Exprs.DependentInits); + Dir->setFinalsConditions(Exprs.FinalsConditions); + Dir->setPreInits(Exprs.PreInits); + Dir->setHasCancel(HasCancel); + return Dir; +} + +OMPMaskedTaskLoopDirective * +OMPMaskedTaskLoopDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, EmptyShell) { + return createEmptyDirective<OMPMaskedTaskLoopDirective>( + C, NumClauses, /*HasAssociatedStmt=*/true, + numLoopChildren(CollapsedNum, OMPD_masked_taskloop), CollapsedNum); +} + OMPMasterTaskLoopSimdDirective *OMPMasterTaskLoopSimdDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, @@ -1200,6 +1265,50 @@ OMPMasterTaskLoopSimdDirective::CreateEmpty(const ASTContext &C, numLoopChildren(CollapsedNum, OMPD_master_taskloop_simd), CollapsedNum); } +OMPMaskedTaskLoopSimdDirective *OMPMaskedTaskLoopSimdDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + auto *Dir = createDirective<OMPMaskedTaskLoopSimdDirective>( + C, Clauses, AssociatedStmt, + numLoopChildren(CollapsedNum, OMPD_masked_taskloop_simd), StartLoc, + EndLoc, CollapsedNum); + 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->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setDependentCounters(Exprs.DependentCounters); + Dir->setDependentInits(Exprs.DependentInits); + Dir->setFinalsConditions(Exprs.FinalsConditions); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPMaskedTaskLoopSimdDirective * +OMPMaskedTaskLoopSimdDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, EmptyShell) { + return createEmptyDirective<OMPMaskedTaskLoopSimdDirective>( + C, NumClauses, /*HasAssociatedStmt=*/true, + numLoopChildren(CollapsedNum, OMPD_masked_taskloop_simd), CollapsedNum); +} + OMPParallelMasterTaskLoopDirective *OMPParallelMasterTaskLoopDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, @@ -1247,6 +1356,53 @@ OMPParallelMasterTaskLoopDirective::CreateEmpty(const ASTContext &C, CollapsedNum); } +OMPParallelMaskedTaskLoopDirective *OMPParallelMaskedTaskLoopDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs, bool HasCancel) { + auto *Dir = createDirective<OMPParallelMaskedTaskLoopDirective>( + C, Clauses, AssociatedStmt, + numLoopChildren(CollapsedNum, OMPD_parallel_masked_taskloop), StartLoc, + EndLoc, CollapsedNum); + 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->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setDependentCounters(Exprs.DependentCounters); + Dir->setDependentInits(Exprs.DependentInits); + Dir->setFinalsConditions(Exprs.FinalsConditions); + Dir->setPreInits(Exprs.PreInits); + Dir->setHasCancel(HasCancel); + return Dir; +} + +OMPParallelMaskedTaskLoopDirective * +OMPParallelMaskedTaskLoopDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + return createEmptyDirective<OMPParallelMaskedTaskLoopDirective>( + C, NumClauses, /*HasAssociatedStmt=*/true, + numLoopChildren(CollapsedNum, OMPD_parallel_masked_taskloop), + CollapsedNum); +} + OMPParallelMasterTaskLoopSimdDirective * OMPParallelMasterTaskLoopSimdDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, @@ -1294,6 +1450,53 @@ OMPParallelMasterTaskLoopSimdDirective::CreateEmpty(const ASTContext &C, CollapsedNum); } +OMPParallelMaskedTaskLoopSimdDirective * +OMPParallelMaskedTaskLoopSimdDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + auto *Dir = createDirective<OMPParallelMaskedTaskLoopSimdDirective>( + C, Clauses, AssociatedStmt, + numLoopChildren(CollapsedNum, OMPD_parallel_masked_taskloop_simd), + StartLoc, EndLoc, CollapsedNum); + 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->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setDependentCounters(Exprs.DependentCounters); + Dir->setDependentInits(Exprs.DependentInits); + Dir->setFinalsConditions(Exprs.FinalsConditions); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPParallelMaskedTaskLoopSimdDirective * +OMPParallelMaskedTaskLoopSimdDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + return createEmptyDirective<OMPParallelMaskedTaskLoopSimdDirective>( + C, NumClauses, /*HasAssociatedStmt=*/true, + numLoopChildren(CollapsedNum, OMPD_parallel_masked_taskloop_simd), + CollapsedNum); +} + OMPDistributeDirective *OMPDistributeDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, @@ -2132,3 +2335,181 @@ OMPGenericLoopDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, C, NumClauses, /*HasAssociatedStmt=*/true, numLoopChildren(CollapsedNum, OMPD_loop), CollapsedNum); } + +OMPTeamsGenericLoopDirective *OMPTeamsGenericLoopDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + auto *Dir = createDirective<OMPTeamsGenericLoopDirective>( + C, Clauses, AssociatedStmt, + numLoopChildren(CollapsedNum, OMPD_teams_loop), StartLoc, EndLoc, + CollapsedNum); + 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->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setDependentCounters(Exprs.DependentCounters); + Dir->setDependentInits(Exprs.DependentInits); + Dir->setFinalsConditions(Exprs.FinalsConditions); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPTeamsGenericLoopDirective * +OMPTeamsGenericLoopDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, EmptyShell) { + return createEmptyDirective<OMPTeamsGenericLoopDirective>( + C, NumClauses, /*HasAssociatedStmt=*/true, + numLoopChildren(CollapsedNum, OMPD_teams_loop), CollapsedNum); +} + +OMPTargetTeamsGenericLoopDirective *OMPTargetTeamsGenericLoopDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + auto *Dir = createDirective<OMPTargetTeamsGenericLoopDirective>( + C, Clauses, AssociatedStmt, + numLoopChildren(CollapsedNum, OMPD_target_teams_loop), StartLoc, EndLoc, + CollapsedNum); + 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->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setDependentCounters(Exprs.DependentCounters); + Dir->setDependentInits(Exprs.DependentInits); + Dir->setFinalsConditions(Exprs.FinalsConditions); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPTargetTeamsGenericLoopDirective * +OMPTargetTeamsGenericLoopDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + return createEmptyDirective<OMPTargetTeamsGenericLoopDirective>( + C, NumClauses, /*HasAssociatedStmt=*/true, + numLoopChildren(CollapsedNum, OMPD_target_teams_loop), CollapsedNum); +} + +OMPParallelGenericLoopDirective *OMPParallelGenericLoopDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + auto *Dir = createDirective<OMPParallelGenericLoopDirective>( + C, Clauses, AssociatedStmt, + numLoopChildren(CollapsedNum, OMPD_parallel_loop), StartLoc, EndLoc, + CollapsedNum); + 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->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setDependentCounters(Exprs.DependentCounters); + Dir->setDependentInits(Exprs.DependentInits); + Dir->setFinalsConditions(Exprs.FinalsConditions); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPParallelGenericLoopDirective *OMPParallelGenericLoopDirective::CreateEmpty( + const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, + EmptyShell) { + return createEmptyDirective<OMPParallelGenericLoopDirective>( + C, NumClauses, /*HasAssociatedStmt=*/true, + numLoopChildren(CollapsedNum, OMPD_parallel_loop), CollapsedNum); +} + +OMPTargetParallelGenericLoopDirective * +OMPTargetParallelGenericLoopDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + auto *Dir = createDirective<OMPTargetParallelGenericLoopDirective>( + C, Clauses, AssociatedStmt, + numLoopChildren(CollapsedNum, OMPD_target_parallel_loop), StartLoc, + EndLoc, CollapsedNum); + 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->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setDependentCounters(Exprs.DependentCounters); + Dir->setDependentInits(Exprs.DependentInits); + Dir->setFinalsConditions(Exprs.FinalsConditions); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPTargetParallelGenericLoopDirective * +OMPTargetParallelGenericLoopDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + return createEmptyDirective<OMPTargetParallelGenericLoopDirective>( + C, NumClauses, /*HasAssociatedStmt=*/true, + numLoopChildren(CollapsedNum, OMPD_target_parallel_loop), CollapsedNum); +} diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index adc0720fe000..8d778500d103 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -128,6 +128,7 @@ namespace { void PrintRawSEHFinallyStmt(SEHFinallyStmt *S); void PrintOMPExecutableDirective(OMPExecutableDirective *S, bool ForceNoStmt = false); + void PrintFPPragmas(CompoundStmt *S); void PrintExpr(Expr *E) { if (E) @@ -174,12 +175,73 @@ namespace { /// with no newline after the }. void StmtPrinter::PrintRawCompoundStmt(CompoundStmt *Node) { OS << "{" << NL; + PrintFPPragmas(Node); for (auto *I : Node->body()) PrintStmt(I); Indent() << "}"; } +void StmtPrinter::PrintFPPragmas(CompoundStmt *S) { + if (!S->hasStoredFPFeatures()) + return; + FPOptionsOverride FPO = S->getStoredFPFeatures(); + bool FEnvAccess = false; + if (FPO.hasAllowFEnvAccessOverride()) { + FEnvAccess = FPO.getAllowFEnvAccessOverride(); + Indent() << "#pragma STDC FENV_ACCESS " << (FEnvAccess ? "ON" : "OFF") + << NL; + } + if (FPO.hasSpecifiedExceptionModeOverride()) { + LangOptions::FPExceptionModeKind EM = + FPO.getSpecifiedExceptionModeOverride(); + if (!FEnvAccess || EM != LangOptions::FPE_Strict) { + Indent() << "#pragma clang fp exceptions("; + switch (FPO.getSpecifiedExceptionModeOverride()) { + default: + break; + case LangOptions::FPE_Ignore: + OS << "ignore"; + break; + case LangOptions::FPE_MayTrap: + OS << "maytrap"; + break; + case LangOptions::FPE_Strict: + OS << "strict"; + break; + } + OS << ")\n"; + } + } + if (FPO.hasConstRoundingModeOverride()) { + LangOptions::RoundingMode RM = FPO.getConstRoundingModeOverride(); + Indent() << "#pragma STDC FENV_ROUND "; + switch (RM) { + case llvm::RoundingMode::TowardZero: + OS << "FE_TOWARDZERO"; + break; + case llvm::RoundingMode::NearestTiesToEven: + OS << "FE_TONEAREST"; + break; + case llvm::RoundingMode::TowardPositive: + OS << "FE_UPWARD"; + break; + case llvm::RoundingMode::TowardNegative: + OS << "FE_DOWNWARD"; + break; + case llvm::RoundingMode::NearestTiesToAway: + OS << "FE_TONEARESTFROMZERO"; + break; + case llvm::RoundingMode::Dynamic: + OS << "FE_DYNAMIC"; + break; + default: + llvm_unreachable("Invalid rounding mode"); + } + OS << NL; + } +} + void StmtPrinter::PrintRawDecl(Decl *D) { D->print(OS, Policy, IndentLevel); } @@ -749,6 +811,12 @@ void StmtPrinter::VisitOMPParallelMasterDirective( PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPParallelMaskedDirective( + OMPParallelMaskedDirective *Node) { + Indent() << "#pragma omp parallel masked"; + PrintOMPExecutableDirective(Node); +} + void StmtPrinter::VisitOMPParallelSectionsDirective( OMPParallelSectionsDirective *Node) { Indent() << "#pragma omp parallel sections"; @@ -874,24 +942,48 @@ void StmtPrinter::VisitOMPMasterTaskLoopDirective( PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPMaskedTaskLoopDirective( + OMPMaskedTaskLoopDirective *Node) { + Indent() << "#pragma omp masked taskloop"; + PrintOMPExecutableDirective(Node); +} + void StmtPrinter::VisitOMPMasterTaskLoopSimdDirective( OMPMasterTaskLoopSimdDirective *Node) { Indent() << "#pragma omp master taskloop simd"; PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPMaskedTaskLoopSimdDirective( + OMPMaskedTaskLoopSimdDirective *Node) { + Indent() << "#pragma omp masked taskloop simd"; + PrintOMPExecutableDirective(Node); +} + void StmtPrinter::VisitOMPParallelMasterTaskLoopDirective( OMPParallelMasterTaskLoopDirective *Node) { Indent() << "#pragma omp parallel master taskloop"; PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPParallelMaskedTaskLoopDirective( + OMPParallelMaskedTaskLoopDirective *Node) { + Indent() << "#pragma omp parallel masked taskloop"; + PrintOMPExecutableDirective(Node); +} + void StmtPrinter::VisitOMPParallelMasterTaskLoopSimdDirective( OMPParallelMasterTaskLoopSimdDirective *Node) { Indent() << "#pragma omp parallel master taskloop simd"; PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPParallelMaskedTaskLoopSimdDirective( + OMPParallelMaskedTaskLoopSimdDirective *Node) { + Indent() << "#pragma omp parallel masked taskloop simd"; + PrintOMPExecutableDirective(Node); +} + void StmtPrinter::VisitOMPDistributeDirective(OMPDistributeDirective *Node) { Indent() << "#pragma omp distribute"; PrintOMPExecutableDirective(Node); @@ -1005,6 +1097,30 @@ void StmtPrinter::VisitOMPGenericLoopDirective(OMPGenericLoopDirective *Node) { PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPTeamsGenericLoopDirective( + OMPTeamsGenericLoopDirective *Node) { + Indent() << "#pragma omp teams loop"; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTargetTeamsGenericLoopDirective( + OMPTargetTeamsGenericLoopDirective *Node) { + Indent() << "#pragma omp target teams loop"; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPParallelGenericLoopDirective( + OMPParallelGenericLoopDirective *Node) { + Indent() << "#pragma omp parallel loop"; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTargetParallelGenericLoopDirective( + OMPTargetParallelGenericLoopDirective *Node) { + Indent() << "#pragma omp target parallel loop"; + PrintOMPExecutableDirective(Node); +} + //===----------------------------------------------------------------------===// // Expr printing methods. //===----------------------------------------------------------------------===// @@ -1023,7 +1139,7 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) { return; } if (const auto *TPOD = dyn_cast<TemplateParamObjectDecl>(Node->getDecl())) { - TPOD->printAsExpr(OS); + TPOD->printAsExpr(OS, Policy); return; } if (NestedNameSpecifier *Qualifier = Node->getQualifier()) @@ -1153,6 +1269,11 @@ void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) { bool isSigned = Node->getType()->isSignedIntegerType(); OS << toString(Node->getValue(), 10, isSigned); + if (isa<BitIntType>(Node->getType())) { + OS << (isSigned ? "wb" : "uwb"); + return; + } + // Emit suffixes. Integer literals are always a builtin integer type. switch (Node->getType()->castAs<BuiltinType>()->getKind()) { default: llvm_unreachable("Unexpected type for integer literal!"); @@ -1736,21 +1857,16 @@ void StmtPrinter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) { } } else if (Kind == OO_Arrow) { PrintExpr(Node->getArg(0)); - } else if (Kind == OO_Call) { + } else if (Kind == OO_Call || Kind == OO_Subscript) { PrintExpr(Node->getArg(0)); - OS << '('; + OS << (Kind == OO_Call ? '(' : '['); for (unsigned ArgIdx = 1; ArgIdx < Node->getNumArgs(); ++ArgIdx) { if (ArgIdx > 1) OS << ", "; if (!isa<CXXDefaultArgExpr>(Node->getArg(ArgIdx))) PrintExpr(Node->getArg(ArgIdx)); } - OS << ')'; - } else if (Kind == OO_Subscript) { - PrintExpr(Node->getArg(0)); - OS << '['; - PrintExpr(Node->getArg(1)); - OS << ']'; + OS << (Kind == OO_Call ? ')' : ']'); } else if (Node->getNumArgs() == 1) { OS << getOperatorSpelling(Kind) << ' '; PrintExpr(Node->getArg(0)); @@ -1945,14 +2061,23 @@ void StmtPrinter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Node) { } void StmtPrinter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) { - Node->getType().print(OS, Policy); - // If there are no parens, this is list-initialization, and the braces are - // part of the syntax of the inner construct. - if (Node->getLParenLoc().isValid()) - OS << "("; + auto TargetType = Node->getType(); + auto *Auto = TargetType->getContainedDeducedType(); + bool Bare = Auto && Auto->isDeduced(); + + // Parenthesize deduced casts. + if (Bare) + OS << '('; + TargetType.print(OS, Policy); + if (Bare) + OS << ')'; + + // No extra braces surrounding the inner construct. + if (!Node->isListInitialization()) + OS << '('; PrintExpr(Node->getSubExpr()); - if (Node->getLParenLoc().isValid()) - OS << ")"; + if (!Node->isListInitialization()) + OS << ')'; } void StmtPrinter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) { @@ -2137,10 +2262,10 @@ void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) { if (E->isParenTypeId()) OS << "("; std::string TypeS; - if (Optional<Expr *> Size = E->getArraySize()) { + if (E->isArray()) { llvm::raw_string_ostream s(TypeS); s << '['; - if (*Size) + if (Optional<Expr *> Size = E->getArraySize()) (*Size)->printPretty(s, Helper, Policy); s << ']'; } @@ -2149,11 +2274,13 @@ void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) { OS << ")"; CXXNewExpr::InitializationStyle InitStyle = E->getInitializationStyle(); - if (InitStyle) { - if (InitStyle == CXXNewExpr::CallInit) + if (InitStyle != CXXNewExpr::NoInit) { + bool Bare = InitStyle == CXXNewExpr::CallInit && + !isa<ParenListExpr>(E->getInitializer()); + if (Bare) OS << "("; PrintExpr(E->getInitializer()); - if (InitStyle == CXXNewExpr::CallInit) + if (Bare) OS << ")"; } } @@ -2215,19 +2342,19 @@ void StmtPrinter::VisitExprWithCleanups(ExprWithCleanups *E) { PrintExpr(E->getSubExpr()); } -void -StmtPrinter::VisitCXXUnresolvedConstructExpr( - CXXUnresolvedConstructExpr *Node) { +void StmtPrinter::VisitCXXUnresolvedConstructExpr( + CXXUnresolvedConstructExpr *Node) { Node->getTypeAsWritten().print(OS, Policy); - OS << "("; - for (CXXUnresolvedConstructExpr::arg_iterator Arg = Node->arg_begin(), - ArgEnd = Node->arg_end(); - Arg != ArgEnd; ++Arg) { + if (!Node->isListInitialization()) + OS << '('; + for (auto Arg = Node->arg_begin(), ArgEnd = Node->arg_end(); Arg != ArgEnd; + ++Arg) { if (Arg != Node->arg_begin()) OS << ", "; PrintExpr(*Arg); } - OS << ")"; + if (!Node->isListInitialization()) + OS << ')'; } void StmtPrinter::VisitCXXDependentScopeMemberExpr( diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 09853e0f0e49..92a8b18cf68a 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -38,6 +38,10 @@ namespace { void VisitStmt(const Stmt *S); + void VisitStmtNoChildren(const Stmt *S) { + HandleStmtClass(S->getStmtClass()); + } + virtual void HandleStmtClass(Stmt::StmtClass SC) = 0; #define STMT(Node, Base) void Visit##Node(const Node *S); @@ -218,7 +222,7 @@ namespace { void StmtProfiler::VisitStmt(const Stmt *S) { assert(S && "Requires non-null Stmt pointer"); - HandleStmtClass(S->getStmtClass()); + VisitStmtNoChildren(S); for (const Stmt *SubStmt : S->children()) { if (SubStmt) @@ -857,6 +861,10 @@ void OMPClauseProfiler::VisitOMPIsDevicePtrClause( const OMPIsDevicePtrClause *C) { VisitOMPClauseList(C); } +void OMPClauseProfiler::VisitOMPHasDeviceAddrClause( + const OMPHasDeviceAddrClause *C) { + VisitOMPClauseList(C); +} void OMPClauseProfiler::VisitOMPNontemporalClause( const OMPNontemporalClause *C) { VisitOMPClauseList(C); @@ -980,6 +988,11 @@ void StmtProfiler::VisitOMPParallelMasterDirective( VisitOMPExecutableDirective(S); } +void StmtProfiler::VisitOMPParallelMaskedDirective( + const OMPParallelMaskedDirective *S) { + VisitOMPExecutableDirective(S); +} + void StmtProfiler::VisitOMPParallelSectionsDirective( const OMPParallelSectionsDirective *S) { VisitOMPExecutableDirective(S); @@ -1082,21 +1095,41 @@ void StmtProfiler::VisitOMPMasterTaskLoopDirective( VisitOMPLoopDirective(S); } +void StmtProfiler::VisitOMPMaskedTaskLoopDirective( + const OMPMaskedTaskLoopDirective *S) { + VisitOMPLoopDirective(S); +} + void StmtProfiler::VisitOMPMasterTaskLoopSimdDirective( const OMPMasterTaskLoopSimdDirective *S) { VisitOMPLoopDirective(S); } +void StmtProfiler::VisitOMPMaskedTaskLoopSimdDirective( + const OMPMaskedTaskLoopSimdDirective *S) { + VisitOMPLoopDirective(S); +} + void StmtProfiler::VisitOMPParallelMasterTaskLoopDirective( const OMPParallelMasterTaskLoopDirective *S) { VisitOMPLoopDirective(S); } +void StmtProfiler::VisitOMPParallelMaskedTaskLoopDirective( + const OMPParallelMaskedTaskLoopDirective *S) { + VisitOMPLoopDirective(S); +} + void StmtProfiler::VisitOMPParallelMasterTaskLoopSimdDirective( const OMPParallelMasterTaskLoopSimdDirective *S) { VisitOMPLoopDirective(S); } +void StmtProfiler::VisitOMPParallelMaskedTaskLoopSimdDirective( + const OMPParallelMaskedTaskLoopSimdDirective *S) { + VisitOMPLoopDirective(S); +} + void StmtProfiler::VisitOMPDistributeDirective( const OMPDistributeDirective *S) { VisitOMPLoopDirective(S); @@ -1203,6 +1236,26 @@ void StmtProfiler::VisitOMPGenericLoopDirective( VisitOMPLoopDirective(S); } +void StmtProfiler::VisitOMPTeamsGenericLoopDirective( + const OMPTeamsGenericLoopDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPTargetTeamsGenericLoopDirective( + const OMPTargetTeamsGenericLoopDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPParallelGenericLoopDirective( + const OMPParallelGenericLoopDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPTargetParallelGenericLoopDirective( + const OMPTargetParallelGenericLoopDirective *S) { + VisitOMPLoopDirective(S); +} + void StmtProfiler::VisitExpr(const Expr *S) { VisitStmt(S); } @@ -1945,7 +1998,11 @@ StmtProfiler::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *S) { void StmtProfiler::VisitLambdaExpr(const LambdaExpr *S) { - VisitExpr(S); + // Do not recursively visit the children of this expression. Profiling the + // body would result in unnecessary work, and is not safe to do during + // deserialization. + VisitStmtNoChildren(S); + // C++20 [temp.over.link]p5: // Two lambda-expressions are never considered equivalent. VisitDecl(S->getLambdaClass()); diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp index 619ce42f9dd1..e0f5916a9a0b 100644 --- a/clang/lib/AST/TemplateBase.cpp +++ b/clang/lib/AST/TemplateBase.cpp @@ -59,15 +59,17 @@ static void printIntegral(const TemplateArgument &TemplArg, raw_ostream &Out, const Type *T = TemplArg.getIntegralType().getTypePtr(); const llvm::APSInt &Val = TemplArg.getAsIntegral(); - if (const EnumType *ET = T->getAs<EnumType>()) { - for (const EnumConstantDecl* ECD : ET->getDecl()->enumerators()) { - // In Sema::CheckTemplateArugment, enum template arguments value are - // extended to the size of the integer underlying the enum type. This - // may create a size difference between the enum value and template - // argument value, requiring isSameValue here instead of operator==. - if (llvm::APSInt::isSameValue(ECD->getInitVal(), Val)) { - ECD->printQualifiedName(Out, Policy); - return; + if (Policy.UseEnumerators) { + if (const EnumType *ET = T->getAs<EnumType>()) { + for (const EnumConstantDecl *ECD : ET->getDecl()->enumerators()) { + // In Sema::CheckTemplateArugment, enum template arguments value are + // extended to the size of the integer underlying the enum type. This + // may create a size difference between the enum value and template + // argument value, requiring isSameValue here instead of operator==. + if (llvm::APSInt::isSameValue(ECD->getInitVal(), Val)) { + ECD->printQualifiedName(Out, Policy); + return; + } } } } @@ -434,7 +436,7 @@ void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out, NamedDecl *ND = getAsDecl(); if (getParamTypeForDecl()->isRecordType()) { if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) { - TPO->printAsInit(Out); + TPO->printAsInit(Out, Policy); break; } } @@ -615,6 +617,17 @@ ASTTemplateArgumentListInfo::Create(const ASTContext &C, return new (Mem) ASTTemplateArgumentListInfo(List); } +const ASTTemplateArgumentListInfo * +ASTTemplateArgumentListInfo::Create(const ASTContext &C, + const ASTTemplateArgumentListInfo *List) { + if (!List) + return nullptr; + std::size_t size = + totalSizeToAlloc<TemplateArgumentLoc>(List->getNumTemplateArgs()); + void *Mem = C.Allocate(size, alignof(ASTTemplateArgumentListInfo)); + return new (Mem) ASTTemplateArgumentListInfo(List); +} + ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo( const TemplateArgumentListInfo &Info) { LAngleLoc = Info.getLAngleLoc(); @@ -626,6 +639,17 @@ ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo( new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); } +ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo( + const ASTTemplateArgumentListInfo *Info) { + LAngleLoc = Info->getLAngleLoc(); + RAngleLoc = Info->getRAngleLoc(); + NumTemplateArgs = Info->getNumTemplateArgs(); + + TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>(); + for (unsigned i = 0; i != NumTemplateArgs; ++i) + new (&ArgBuffer[i]) TemplateArgumentLoc((*Info)[i]); +} + void ASTTemplateKWAndArgsInfo::initializeFrom( SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info, TemplateArgumentLoc *OutArgArray) { diff --git a/clang/lib/AST/TemplateName.cpp b/clang/lib/AST/TemplateName.cpp index 05d7d58b71c4..11dc3d2e1985 100644 --- a/clang/lib/AST/TemplateName.cpp +++ b/clang/lib/AST/TemplateName.cpp @@ -13,6 +13,7 @@ #include "clang/AST/TemplateName.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DependenceFlags.h" #include "clang/AST/NestedNameSpecifier.h" @@ -76,12 +77,18 @@ TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage) : Storage(Storage) {} TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {} TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {} +TemplateName::TemplateName(UsingShadowDecl *Using) : Storage(Using) {} bool TemplateName::isNull() const { return Storage.isNull(); } TemplateName::NameKind TemplateName::getKind() const { - if (Storage.is<TemplateDecl *>()) + if (auto *ND = Storage.dyn_cast<Decl *>()) { + if (isa<UsingShadowDecl>(ND)) + return UsingTemplate; + assert(isa<TemplateDecl>(ND)); return Template; + } + if (Storage.is<DependentTemplateName *>()) return DependentTemplate; if (Storage.is<QualifiedTemplateName *>()) @@ -99,15 +106,23 @@ TemplateName::NameKind TemplateName::getKind() const { } TemplateDecl *TemplateName::getAsTemplateDecl() const { - if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) - return Template; + if (Decl *TemplateOrUsing = Storage.dyn_cast<Decl *>()) { + if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(TemplateOrUsing)) + return cast<TemplateDecl>(USD->getTargetDecl()); + + assert(isa<TemplateDecl>(TemplateOrUsing)); + return cast<TemplateDecl>(TemplateOrUsing); + } if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) - return QTN->getTemplateDecl(); + return QTN->getUnderlyingTemplate().getAsTemplateDecl(); if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm()) return sub->getReplacement().getAsTemplateDecl(); + if (UsingShadowDecl *USD = getAsUsingShadowDecl()) + return cast<TemplateDecl>(USD->getTargetDecl()); + return nullptr; } @@ -153,6 +168,15 @@ DependentTemplateName *TemplateName::getAsDependentTemplateName() const { return Storage.dyn_cast<DependentTemplateName *>(); } +UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const { + if (Decl *D = Storage.dyn_cast<Decl *>()) + if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) + return USD; + if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) + return QTN->getUnderlyingTemplate().getAsUsingShadowDecl(); + return nullptr; +} + TemplateName TemplateName::getNameToSubstitute() const { TemplateDecl *Decl = getAsTemplateDecl(); @@ -222,7 +246,22 @@ bool TemplateName::containsUnexpandedParameterPack() const { void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, Qualified Qual) const { - if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) + auto Kind = getKind(); + TemplateDecl *Template = nullptr; + if (Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) { + // After `namespace ns { using std::vector }`, what is the fully-qualified + // name of the UsingTemplateName `vector` within ns? + // + // - ns::vector (the qualified name of the using-shadow decl) + // - std::vector (the qualified name of the underlying template decl) + // + // Similar to the UsingType behavior, using declarations are used to import + // names more often than to export them, thus using the original name is + // most useful in this case. + Template = getAsTemplateDecl(); + } + + if (Template) if (Policy.CleanUglifiedParameters && isa<TemplateTemplateParmDecl>(Template) && Template->getIdentifier()) OS << Template->getIdentifier()->deuglifiedName(); @@ -236,14 +275,15 @@ void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, if (Qual == Qualified::Fully && getDependence() != TemplateNameDependenceScope::DependentInstantiation) { - QTN->getTemplateDecl()->printQualifiedName(OS, Policy); + QTN->getUnderlyingTemplate().getAsTemplateDecl()->printQualifiedName( + OS, Policy); return; } if (Qual == Qualified::AsWritten) QTN->getQualifier()->print(OS, Policy); if (QTN->hasTemplateKeyword()) OS << "template "; - OS << *QTN->getDecl(); + OS << *QTN->getUnderlyingTemplate().getAsTemplateDecl(); } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) { if (Qual == Qualified::AsWritten && DTN->getQualifier()) DTN->getQualifier()->print(OS, Policy); @@ -262,6 +302,7 @@ void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) { Assumed->getDeclName().print(OS, Policy); } else { + assert(getKind() == TemplateName::OverloadedTemplate); OverloadedTemplateStorage *OTS = getAsOverloadedTemplate(); (*OTS->begin())->printName(OS); } diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 67c934847c7f..79e9fa6ab86f 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -283,6 +283,8 @@ void TextNodeDumper::Visit(const Decl *D) { OS << " constexpr"; if (FD->isConsteval()) OS << " consteval"; + if (FD->isMultiVersion()) + OS << " multiversion"; } if (!isa<FunctionDecl>(*D)) { @@ -898,12 +900,17 @@ void TextNodeDumper::VisitIntegralTemplateArgument(const TemplateArgument &TA) { } void TextNodeDumper::VisitTemplateTemplateArgument(const TemplateArgument &TA) { + if (TA.getAsTemplate().getKind() == TemplateName::UsingTemplate) + OS << " using"; OS << " template "; TA.getAsTemplate().dump(OS); } void TextNodeDumper::VisitTemplateExpansionTemplateArgument( const TemplateArgument &TA) { + if (TA.getAsTemplateOrTemplatePattern().getKind() == + TemplateName::UsingTemplate) + OS << " using"; OS << " template expansion "; TA.getAsTemplateOrTemplatePattern().dump(OS); } @@ -1573,10 +1580,18 @@ void TextNodeDumper::VisitAutoType(const AutoType *T) { } } +void TextNodeDumper::VisitDeducedTemplateSpecializationType( + const DeducedTemplateSpecializationType *T) { + if (T->getTemplateName().getKind() == TemplateName::UsingTemplate) + OS << " using"; +} + void TextNodeDumper::VisitTemplateSpecializationType( const TemplateSpecializationType *T) { if (T->isTypeAlias()) OS << " alias"; + if (T->getTemplateName().getKind() == TemplateName::UsingTemplate) + OS << " using"; OS << " "; T->getTemplateName().dump(OS); } @@ -1666,6 +1681,9 @@ void TextNodeDumper::VisitFunctionDecl(const FunctionDecl *D) { if (D->isTrivial()) OS << " trivial"; + if (D->isIneligibleOrNotSelected()) + OS << (isa<CXXDestructorDecl>(D) ? " not_selected" : " ineligible"); + if (const auto *FPT = D->getType()->getAs<FunctionProtoType>()) { FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); switch (EPI.ExceptionSpec.Type) { @@ -2353,3 +2371,9 @@ void TextNodeDumper::VisitBlockDecl(const BlockDecl *D) { void TextNodeDumper::VisitConceptDecl(const ConceptDecl *D) { dumpName(D); } + +void TextNodeDumper::VisitCompoundStmt(const CompoundStmt *S) { + VisitStmt(S); + if (S->hasStoredFPFeatures()) + printFPOptions(S->getStoredFPFeatures()); +} diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 774b3e94159d..0f168a518707 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -722,8 +722,7 @@ bool Type::isObjCClassOrClassKindOfType() const { ObjCTypeParamType::ObjCTypeParamType(const ObjCTypeParamDecl *D, QualType can, ArrayRef<ObjCProtocolDecl *> protocols) - : Type(ObjCTypeParam, can, - can->getDependence() & ~TypeDependence::UnexpandedPack), + : Type(ObjCTypeParam, can, toSemanticDependence(can->getDependence())), OTPDecl(const_cast<ObjCTypeParamDecl *>(D)) { initialize(protocols); } @@ -1899,8 +1898,14 @@ bool Type::hasAutoForTrailingReturnType() const { bool Type::hasIntegerRepresentation() const { if (const auto *VT = dyn_cast<VectorType>(CanonicalType)) return VT->getElementType()->isIntegerType(); - else - return isIntegerType(); + if (CanonicalType->isVLSTBuiltinType()) { + const auto *VT = cast<BuiltinType>(CanonicalType); + return VT->getKind() == BuiltinType::SveBool || + (VT->getKind() >= BuiltinType::SveInt8 && + VT->getKind() <= BuiltinType::SveUint64); + } + + return isIntegerType(); } /// Determine whether this type is an integral type. @@ -2105,6 +2110,11 @@ bool Type::hasUnsignedIntegerRepresentation() const { return VT->getElementType()->isUnsignedIntegerOrEnumerationType(); if (const auto *VT = dyn_cast<MatrixType>(CanonicalType)) return VT->getElementType()->isUnsignedIntegerOrEnumerationType(); + if (CanonicalType->isVLSTBuiltinType()) { + const auto *VT = cast<BuiltinType>(CanonicalType); + return VT->getKind() >= BuiltinType::SveUint8 && + VT->getKind() <= BuiltinType::SveUint64; + } return isUnsignedIntegerOrEnumerationType(); } @@ -2495,6 +2505,25 @@ bool QualType::isTriviallyCopyableType(const ASTContext &Context) const { return false; } +bool QualType::isTriviallyRelocatableType(const ASTContext &Context) const { + QualType BaseElementType = Context.getBaseElementType(*this); + + if (BaseElementType->isIncompleteType()) { + return false; + } else if (const auto *RD = BaseElementType->getAsRecordDecl()) { + return RD->canPassInRegisters(); + } else { + switch (isNonTrivialToPrimitiveDestructiveMove()) { + case PCK_Trivial: + return !isDestructedType(); + case PCK_ARCStrong: + return true; + default: + return false; + } + } +} + bool QualType::isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const { return !Context.getLangOpts().ObjCAutoRefCount && Context.getLangOpts().ObjCWeak && @@ -3156,6 +3185,8 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { case CC_AAPCS: return "aapcs"; case CC_AAPCS_VFP: return "aapcs-vfp"; case CC_AArch64VectorCall: return "aarch64_vector_pcs"; + case CC_AArch64SVEPCS: return "aarch64_sve_pcs"; + case CC_AMDGPUKernelCall: return "amdgpu_kernel"; case CC_IntelOclBicc: return "intel_ocl_bicc"; case CC_SpirFunction: return "spir_function"; case CC_OpenCLKernel: return "opencl_kernel"; @@ -3182,12 +3213,15 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, FunctionTypeBits.Variadic = epi.Variadic; FunctionTypeBits.HasTrailingReturn = epi.HasTrailingReturn; - // Fill in the extra trailing bitfields if present. - if (hasExtraBitfields(epi.ExceptionSpec.Type)) { + if (epi.requiresFunctionProtoTypeExtraBitfields()) { + FunctionTypeBits.HasExtraBitfields = true; auto &ExtraBits = *getTrailingObjects<FunctionTypeExtraBitfields>(); - ExtraBits.NumExceptionType = epi.ExceptionSpec.Exceptions.size(); + ExtraBits = FunctionTypeExtraBitfields(); + } else { + FunctionTypeBits.HasExtraBitfields = false; } + // Fill in the trailing argument array. auto *argSlot = getTrailingObjects<QualType>(); for (unsigned i = 0; i != getNumParams(); ++i) { @@ -3198,6 +3232,9 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, // Fill in the exception type array if present. if (getExceptionSpecType() == EST_Dynamic) { + auto &ExtraBits = *getTrailingObjects<FunctionTypeExtraBitfields>(); + ExtraBits.NumExceptionType = epi.ExceptionSpec.Exceptions.size(); + assert(hasExtraBitfields() && "missing trailing extra bitfields!"); auto *exnSlot = reinterpret_cast<QualType *>(getTrailingObjects<ExceptionType>()); @@ -3301,7 +3338,6 @@ CanThrowResult FunctionProtoType::canThrow() const { switch (getExceptionSpecType()) { case EST_Unparsed: case EST_Unevaluated: - case EST_Uninstantiated: llvm_unreachable("should not call this with unresolved exception specs"); case EST_DynamicNone: @@ -3323,6 +3359,7 @@ CanThrowResult FunctionProtoType::canThrow() const { return CT_Can; return CT_Dependent; + case EST_Uninstantiated: case EST_DependentNoexcept: return CT_Dependent; } @@ -3398,7 +3435,7 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, TypedefType::TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType underlying, QualType can) - : Type(tc, can, underlying->getDependence()), + : Type(tc, can, toSemanticDependence(underlying->getDependence())), Decl(const_cast<TypedefNameDecl *>(D)) { assert(!isa<TypedefType>(can) && "Invalid canonical type"); } @@ -3409,7 +3446,7 @@ QualType TypedefType::desugar() const { UsingType::UsingType(const UsingShadowDecl *Found, QualType Underlying, QualType Canon) - : Type(Using, Canon, Underlying->getDependence()), + : Type(Using, Canon, toSemanticDependence(Underlying->getDependence())), Found(const_cast<UsingShadowDecl *>(Found)) { assert(Underlying == getUnderlyingType()); } @@ -3591,6 +3628,8 @@ bool AttributedType::isCallingConv() const { case attr::SwiftAsyncCall: case attr::VectorCall: case attr::AArch64VectorPcs: + case attr::AArch64SVEPcs: + case attr::AMDGPUKernelCall: case attr::Pascal: case attr::MSABI: case attr::SysVABI: @@ -3665,8 +3704,7 @@ TemplateSpecializationType::TemplateSpecializationType( : Type(TemplateSpecialization, Canon.isNull() ? QualType(this, 0) : Canon, (Canon.isNull() ? TypeDependence::DependentInstantiation - : Canon->getDependence() & ~(TypeDependence::VariablyModified | - TypeDependence::UnexpandedPack)) | + : toSemanticDependence(Canon->getDependence())) | (toTypeDependence(T.getDependence()) & TypeDependence::UnexpandedPack)), Template(T) { @@ -3677,7 +3715,8 @@ TemplateSpecializationType::TemplateSpecializationType( "Use DependentTemplateSpecializationType for dependent template-name"); assert((T.getKind() == TemplateName::Template || T.getKind() == TemplateName::SubstTemplateTemplateParm || - T.getKind() == TemplateName::SubstTemplateTemplateParmPack) && + T.getKind() == TemplateName::SubstTemplateTemplateParmPack || + T.getKind() == TemplateName::UsingTemplate) && "Unexpected template name for TemplateSpecializationType"); auto *TemplateArgs = reinterpret_cast<TemplateArgument *>(this + 1); diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp index 13aa54c48f66..cf5e2f979230 100644 --- a/clang/lib/AST/TypeLoc.cpp +++ b/clang/lib/AST/TypeLoc.cpp @@ -507,6 +507,10 @@ SourceRange AttributedTypeLoc::getLocalSourceRange() const { return getAttr() ? getAttr()->getRange() : SourceRange(); } +SourceRange BTFTagAttributedTypeLoc::getLocalSourceRange() const { + return getAttr() ? getAttr()->getRange() : SourceRange(); +} + void TypeOfTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) { TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> @@ -683,6 +687,10 @@ namespace { return Visit(T.getModifiedLoc()); } + TypeLoc VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc T) { + return Visit(T.getWrappedLoc()); + } + TypeLoc VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc T) { return Visit(T.getInnerLoc()); } diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index bba323f651aa..6b13d3806037 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -80,6 +80,21 @@ namespace { } }; + class DefaultTemplateArgsPolicyRAII { + PrintingPolicy &Policy; + bool Old; + + public: + explicit DefaultTemplateArgsPolicyRAII(PrintingPolicy &Policy) + : Policy(Policy), Old(Policy.SuppressDefaultTemplateArgs) { + Policy.SuppressDefaultTemplateArgs = false; + } + + ~DefaultTemplateArgsPolicyRAII() { + Policy.SuppressDefaultTemplateArgs = Old; + } + }; + class ElaboratedTypePolicyRAII { PrintingPolicy &Policy; bool SuppressTagKeyword; @@ -235,6 +250,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::Pipe: case Type::BitInt: case Type::DependentBitInt: + case Type::BTFTagAttributed: CanPrefixQualifiers = true; break; @@ -282,6 +298,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, // address_space attribute. const auto *AttrTy = cast<AttributedType>(UnderlyingType); CanPrefixQualifiers = AttrTy->getAttrKind() == attr::AddressSpace; + break; } } @@ -959,6 +976,12 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info, case CC_AArch64VectorCall: OS << "__attribute__((aarch64_vector_pcs))"; break; + case CC_AArch64SVEPCS: + OS << "__attribute__((aarch64_sve_pcs))"; + break; + case CC_AMDGPUKernelCall: + OS << "__attribute__((amdgpu_kernel))"; + break; case CC_IntelOclBicc: OS << " __attribute__((intel_ocl_bicc))"; break; @@ -1462,17 +1485,19 @@ void TypePrinter::printTemplateId(const TemplateSpecializationType *T, IncludeStrongLifetimeRAII Strong(Policy); TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl(); + // FIXME: Null TD never excercised in test suite. if (FullyQualify && TD) { if (!Policy.SuppressScope) AppendScope(TD->getDeclContext(), OS, TD->getDeclName()); - IdentifierInfo *II = TD->getIdentifier(); - OS << II->getName(); + OS << TD->getName(); } else { T->getTemplateName().print(OS, Policy); } - printTemplateArgumentList(OS, T->template_arguments(), Policy); + DefaultTemplateArgsPolicyRAII TemplateArgs(Policy); + const TemplateParameterList *TPL = TD ? TD->getTemplateParameters() : nullptr; + printTemplateArgumentList(OS, T->template_arguments(), Policy, TPL); spaceBeforePlaceHolder(OS); } @@ -1681,6 +1706,15 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, if (T->getAttrKind() == attr::AddressSpace) return; + if (T->getAttrKind() == attr::AnnotateType) { + // FIXME: Print the attribute arguments once we have a way to retrieve these + // here. For the meantime, we just print `[[clang::annotate_type(...)]]` + // without the arguments so that we know at least that we had _some_ + // annotation on the type. + OS << " [[clang::annotate_type(...)]]"; + return; + } + OS << " __attribute__(("; switch (T->getAttrKind()) { #define TYPE_ATTR(NAME) @@ -1689,6 +1723,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, #include "clang/Basic/AttrList.inc" llvm_unreachable("non-type attribute attached to type"); + case attr::BTFTypeTag: + llvm_unreachable("BTFTypeTag attribute handled separately"); + case attr::OpenCLPrivateAddressSpace: case attr::OpenCLGlobalAddressSpace: case attr::OpenCLGlobalDeviceAddressSpace: @@ -1715,6 +1752,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, case attr::UPtr: case attr::AddressSpace: case attr::CmseNSCall: + case attr::AnnotateType: llvm_unreachable("This attribute should have been handled already"); case attr::NSReturnsRetained: @@ -1746,6 +1784,8 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, break; } case attr::AArch64VectorPcs: OS << "aarch64_vector_pcs"; break; + case attr::AArch64SVEPcs: OS << "aarch64_sve_pcs"; break; + case attr::AMDGPUKernelCall: OS << "amdgpu_kernel"; break; case attr::IntelOclBicc: OS << "inteloclbicc"; break; case attr::PreserveMost: OS << "preserve_most"; @@ -1763,13 +1803,21 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, case attr::ArmMveStrictPolymorphism: OS << "__clang_arm_mve_strict_polymorphism"; break; - case attr::BTFTypeTag: - OS << "btf_type_tag"; - break; } OS << "))"; } +void TypePrinter::printBTFTagAttributedBefore(const BTFTagAttributedType *T, + raw_ostream &OS) { + printBefore(T->getWrappedType(), OS); + OS << " btf_type_tag(" << T->getAttr()->getBTFTypeTag() << ")"; +} + +void TypePrinter::printBTFTagAttributedAfter(const BTFTagAttributedType *T, + raw_ostream &OS) { + printAfter(T->getWrappedType(), OS); +} + void TypePrinter::printObjCInterfaceBefore(const ObjCInterfaceType *T, raw_ostream &OS) { OS << T->getDecl()->getName(); @@ -2295,3 +2343,9 @@ void QualType::getAsStringInternal(const Type *ty, Qualifiers qs, std::string str = std::string(StrOS.str()); buffer.swap(str); } + +raw_ostream &clang::operator<<(raw_ostream &OS, QualType QT) { + SplitQualType S = QT.split(); + TypePrinter(LangOptions()).print(S.Ty, S.Quals, OS, /*PlaceHolder=*/""); + return OS; +} diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp index 24586d6b70d4..3d64cb17fa9c 100644 --- a/clang/lib/AST/VTableBuilder.cpp +++ b/clang/lib/AST/VTableBuilder.cpp @@ -17,6 +17,7 @@ #include "clang/AST/RecordLayout.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/SetOperations.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" @@ -3113,8 +3114,7 @@ static void dumpMicrosoftThunkAdjustment(const ThunkInfo &TI, raw_ostream &Out, if (!ContinueFirstLine) Out << LinePrefix; Out << "[return adjustment (to type '" - << TI.Method->getReturnType().getCanonicalType().getAsString() - << "'): "; + << TI.Method->getReturnType().getCanonicalType() << "'): "; if (R.Virtual.Microsoft.VBPtrOffset) Out << "vbptr at offset " << R.Virtual.Microsoft.VBPtrOffset << ", "; if (R.Virtual.Microsoft.VBIndex) @@ -3384,10 +3384,8 @@ 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. - llvm::SmallVector<std::reference_wrapper<VPtrInfo>, 2> PathsSorted; - PathsSorted.reserve(Paths.size()); - for (auto& P : Paths) - PathsSorted.push_back(*P); + llvm::SmallVector<std::reference_wrapper<VPtrInfo>, 2> PathsSorted( + llvm::make_pointee_range(Paths)); llvm::sort(PathsSorted, [](const VPtrInfo &LHS, const VPtrInfo &RHS) { return LHS.MangledPath < RHS.MangledPath; }); |
